C'est évidemment le bon langage pour la tâche. : ^ D
s:({c<L>}{c<R>}0[(<R> <L>)(<L> <R>)_?])%{30}
c:0 *$
Correspond à l'entrée entière s'il s'agit d'un serpent valide; ne correspond pas si ce n'est pas le cas. Essayez-le ici!
Explication
SnakeEx est un langage de correspondance de motifs 2D . Un programme se compose d'une liste de définitions de «serpents», qui rampent autour des caractères correspondants en entrée, changent de direction et engendrent d'autres serpents. Dans notre programme, nous définissons deux serpents, s
et c
.
Nous allons commencer par c
parce que c'est plus simple. Sa définition est 0 *$
, ce qui devrait être assez lisible si vous connaissez regex: match 0
, suivi de zéro ou plusieurs espaces, suivi du bord de la grille. Le principal hic ici: cet appariement peut se faire dans n'importe quelle direction. Nous allons utiliser à la c
fois vers le haut et vers le bas à partir du serpent, pour vérifier qu'il n'y a pas de supplément0
s dans chaque colonne.
Maintenant pour le serpent principal, s
. Il prend la forme (...)%{30}
, ce qui signifie «faire correspondre le contenu des parenthèses 30 fois» - une fois pour chacune 0
chez le serpent. Jusqu'ici tout va bien. Qu'y a-t-il entre les parenthèses?
{c<L>}
Cela engendre un nouveau c
serpent, tourné à gauche de 90 degrés. La direction est relative à las
direction du serpent, donc le nouveau serpent se déplace vers le haut de la grille (le serpent principal se déplace vers la droite). Le c
serpent vérifie que la cellule de grille actuelle est un 0
et que chaque cellule au-dessus est un espace. S'il échoue, la correspondance entière échoue. S'il réussit, nous continuons avec
{c<R>}
qui fait la même chose, seulement tourné à droite (vers le bas de la grille).
Notez que ces apparitions n'affectent pas la position du pointeur de correspondance dans le serpent principal. Ils sont un peu comme des lookaheads en regex. (Peut-être que nous pourrions les appeler ici "lookbesides"?) Donc, après avoir vérifié que nous pointons sur un 0
et que le reste de la colonne ne contient que des espaces, nous devons réellement faire correspondre le0
:
0
Maintenant, le pointeur de correspondance se trouve sur le caractère à droite de la 0
. Nous devons vérifier trois options différentes: le serpent s'incline vers le bas, le serpent s'incline vers le haut ou le serpent va droit. Pour cela, nous pouvons utiliser une expression OR:
[...]
À l'intérieur de notre salle d'opération, nous avons trois possibilités:
(<R> <L>)
Tournez à droite, faites correspondre un espace et tournez à gauche à nouveau (angles de serpent vers le bas).
(<L> <R>)
Tournez à gauche, faites correspondre un espace et tournez à nouveau à droite (angles de serpent vers le haut).
_?
Faites correspondre zéro ou un trait de soulignement. Puisqu'il n'y a pas de soulignement dans l'entrée, ce sera toujours une correspondance vide (le serpent va droit).
Après avoir correspondu à l'une des trois options ci-dessus, le pointeur de correspondance doit pointer vers 0
dans la colonne suivante, prêt à correspondre à nouveau à l'expression entre parenthèses.