Este es obviamente el lenguaje correcto para la tarea. : ^ D
s:({c<L>}{c<R>}0[(<R> <L>)(<L> <R>)_?])%{30}
c:0 *$
Coincide con la entrada completa si es una serpiente válida; no coincide si no es así. Pruébalo aquí!
Explicación
SnakeEx es un lenguaje de coincidencia de patrones 2D . Un programa consiste en una lista de definiciones para "serpientes", que se arrastran alrededor de los caracteres coincidentes de entrada, cambian de dirección y generan otras serpientes. En nuestro programa, definimos dos serpientes, s
yc
.
Comenzaremos c
porque es más simple. Su definición es 0 *$
, que debería ser bastante legible si conoce regex: match 0
, seguido de cero o más espacios, seguido del borde de la cuadrícula. El problema principal aquí: esta coincidencia puede proceder en cualquier dirección. Vamos a usarc
tanto hacia arriba como hacia abajo desde la serpiente, para verificar que no haya 0
s adicionales en cada columna.
Ya por la serpiente principal s
. Toma la forma (...)%{30}
, que significa "hacer coincidir el contenido de los paréntesis 30 veces", una vez para cada uno 0
en la serpiente. Hasta aquí todo bien. ¿Qué va dentro de los paréntesis?
{c<L>}
Esto genera una nueva c
serpiente, giró a la izquierda 90 grados. La dirección es relativa a la s
dirección de la serpiente, por lo que la nueva serpiente se mueve hacia la parte superior de la cuadrícula (la serpiente principal se mueve hacia la derecha). La c
serpiente comprueba que la celda de la cuadrícula actual es una 0
y que cada celda de arriba es un espacio. Si falla, toda la partida falla. Si tiene éxito, continuamos con
{c<R>}
que hace lo mismo, solo giró a la derecha (hacia la parte inferior de la cuadrícula).
Tenga en cuenta que estos engendros no afectan la posición del puntero de coincidencia en la serpiente principal. Son un poco como lookaheads en regex. (¿Tal vez aquí podríamos llamarlos "lookbesides"?) Entonces, después de verificar que estamos apuntando a a 0
y que el resto de la columna contiene solo espacios, necesitamos hacer coincidir 0
:
0
Ahora el puntero de coincidencia está en el carácter a la derecha de 0
. Necesitamos verificar tres opciones diferentes: la serpiente se inclina hacia abajo, la serpiente se inclina hacia arriba o la serpiente se endereza. Para esto, podemos usar una expresión OR:
[...]
Dentro de nuestro quirófano, tenemos tres posibilidades:
(<R> <L>)
Gire a la derecha, haga coincidir un espacio y gire a la izquierda nuevamente (ángulos de serpiente hacia abajo).
(<L> <R>)
Gire a la izquierda, combine un espacio y gire a la derecha nuevamente (la serpiente se inclina hacia arriba).
_?
Haga coincidir cero o uno con guiones bajos. Como no hay guiones bajos en la entrada, esta siempre será una coincidencia vacía (la serpiente va en línea recta).
Después de hacer coincidir una de las tres opciones anteriores, el puntero de coincidencia debe apuntar a la 0
en la siguiente columna, listo para coincidir nuevamente con la expresión entre paréntesis.