Esse é obviamente o idioma certo para a tarefa. : ^ D
s:({c<L>}{c<R>}0[(<R> <L>)(<L> <R>)_?])%{30}
c:0 *$
Corresponde a entrada inteira se for uma cobra válida; falha em corresponder se não estiver. Experimente aqui!
Explicação
SnakeEx é uma linguagem de correspondência de padrões 2D . Um programa consiste em uma lista de definições para "cobras", que rastreiam os caracteres correspondentes de entrada, mudam de direção e geram outras cobras. Em nosso programa, definimos duas cobras, s
e c
.
Vamos começar c
porque é mais simples. Sua definição é 0 *$
, que deve ser bastante legível se você souber regex: match 0
, seguido por zero ou mais espaços, seguido pela borda da grade. O principal problema aqui: essa correspondência pode prosseguir em qualquer direção. Vamos usar para c
cima e para baixo da cobra, para verificar se não há 0
s extras em cada coluna.
Agora para a cobra principal s
,. Ele assume a forma (...)%{30}
, que significa "combinar o conteúdo dos parênteses 30 vezes" - uma vez para cada um 0
na cobra. Por enquanto, tudo bem. O que se passa dentro dos parênteses?
{c<L>}
Isso gera uma nova c
cobra, virou à esquerda 90 graus. A direção é relativa à s
direção da cobra, então a nova cobra se move em direção ao topo da grade (a cobra principal está se movendo em direção à direita). A c
cobra verifica se a célula da grade atual é uma 0
e se todas as células acima dela são um espaço. Se falhar, a correspondência inteira falhará. Se for bem-sucedido, continuamos com
{c<R>}
que faz a mesma coisa, apenas virou à direita (na parte inferior da grade).
Observe que esses spawns não afetam a posição do ponteiro da partida na cobra principal. Eles são um pouco parecidos com lookaheads no regex. (Talvez aqui possamos chamá-los de "lookbesides"?). Depois de verificar se estamos apontando para ae 0
o restante da coluna contém apenas espaços, precisamos realmente corresponder a 0
:
0
Agora, o ponteiro da partida está no caractere à direita do 0
. Precisamos verificar três opções diferentes: a cobra inclina-se para baixo, a cobra inclina-se para cima ou a cobra segue em linha reta. Para isso, podemos usar uma expressão OR:
[...]
Dentro da nossa sala de cirurgia, temos três possibilidades:
(<R> <L>)
Vire à direita, combine um espaço e vire novamente à esquerda (ângulos de cobra para baixo).
(<L> <R>)
Vire à esquerda, combine um espaço e vire à direita novamente (a cobra está inclinada para cima).
_?
Corresponder zero ou um sublinhado. Como não há sublinhados na entrada, sempre será uma correspondência vazia (a cobra vai direto).
Depois de corresponder a uma das três opções acima, o ponteiro de correspondência deve estar apontando para o 0
na próxima coluna, pronto para corresponder à expressão entre parênteses novamente.