Questa è ovviamente la lingua giusta per l'attività. : ^ D
s:({c<L>}{c<R>}0[(<R> <L>)(<L> <R>)_?])%{30}
c:0 *$
Corrisponde all'intero input se è un serpente valido; non riesce a corrispondere se non lo è. Provalo qui!
Spiegazione
SnakeEx è un linguaggio di corrispondenza del modello 2D . Un programma consiste in un elenco di definizioni per "serpenti", che strisciano attorno ai caratteri corrispondenti all'input, cambiando direzione e generando altri serpenti. Nel nostro programma, definiamo due serpenti s
e c
.
Inizieremo c
perché è più semplice. La sua definizione è 0 *$
, che dovrebbe essere abbastanza leggibile se conosci regex: match 0
, seguito da zero o più spazi, seguito dal bordo della griglia. Il principale vantaggio qui: questa corrispondenza può procedere in qualsiasi direzione. Useremo c
sia verso l'alto che verso il basso dal serpente, per verificare che non ci siano messaggi extra 0
in ogni colonna.
Ora, per il serpente principale s
. Prende la forma (...)%{30}
, che significa "abbina il contenuto delle parentesi 30 volte" - una volta per ciascuna 0
nel serpente. Fin qui tutto bene. Cosa c'è tra parentesi?
{c<L>}
Questo genera un nuovo c
serpente, girato a sinistra di 90 gradi. La direzione è relativa alla s
direzione del serpente, quindi il nuovo serpente si sposta verso la parte superiore della griglia (il serpente principale si sta muovendo verso destra). Il c
serpente verifica che la cella della griglia corrente sia una 0
e che ogni cella sopra di essa sia uno spazio. Se fallisce, l'intera partita fallisce. Se ci riesce, continuiamo con
{c<R>}
che fa la stessa cosa, solo girato a destra (verso il fondo della griglia).
Nota che queste spawn non influiscono sulla posizione del puntatore della partita nel serpente principale. Sono un po 'come lookaheads in regex. (Forse qui potremmo chiamarli "lookbesides"?) Quindi, dopo aver verificato che stiamo puntando a 0
e il resto della colonna contiene solo spazi, dobbiamo effettivamente abbinare 0
:
0
Ora il puntatore della partita si trova sul personaggio a destra del 0
. Dobbiamo controllare tre diverse opzioni: il serpente si inclina verso il basso, il serpente si inclina verso l'alto o il serpente va dritto. Per questo, possiamo usare un'espressione OR:
[...]
All'interno del nostro OR, abbiamo tre possibilità:
(<R> <L>)
Gira a destra, abbina uno spazio e gira di nuovo a sinistra (angoli di serpente verso il basso).
(<L> <R>)
Gira a sinistra, abbina uno spazio e gira di nuovo a destra (angoli del serpente in alto).
_?
Abbina zero o un trattino basso. Poiché non ci sono caratteri di sottolineatura nell'input, questa sarà sempre una corrispondenza vuota (il serpente va dritto).
Dopo aver abbinato una delle tre opzioni precedenti, il puntatore di corrispondenza dovrebbe puntare alla 0
colonna successiva, pronto per abbinare nuovamente l'espressione tra parentesi.