Ini jelas bahasa yang tepat untuk tugas itu. : ^ D
s:({c<L>}{c<R>}0[(<R> <L>)(<L> <R>)_?])%{30}
c:0 *$
Cocokkan seluruh input jika itu adalah ular yang valid; gagal mencocokkan jika tidak. Coba di sini!
Penjelasan
SnakeEx adalah bahasa pencocokan pola 2-D . Suatu program terdiri dari daftar definisi untuk "ular," yang merangkak di sekitar karakter pencocokan input, mengubah arah, dan memunculkan ular lain. Dalam program kami, kami mendefinisikan dua ular, s
dan c
.
Kami akan mulai dengan c
karena lebih sederhana. Definisinya adalah 0 *$
, yang seharusnya cukup mudah dibaca jika Anda tahu regex: match 0
, diikuti oleh nol atau lebih banyak ruang, diikuti oleh tepi grid. Tangkapan utama di sini: pencocokan ini dapat dilanjutkan ke segala arah. Kita akan menggunakan c
ke atas dan ke bawah dari ular, untuk memverifikasi bahwa tidak ada tambahan 0
di setiap kolom.
Sekarang untuk ular utama s
,. Itu mengambil bentuk (...)%{30}
, yang berarti "cocokkan dengan isi kurung 30 kali" - satu kali untuk masing-masing 0
ular. Sejauh ini baik. Apa yang ada di dalam tanda kurung?
{c<L>}
Ini memunculkan c
ular baru , belok kiri 90 derajat. Arahnya relatif terhadap arah s
ular, sehingga ular baru itu bergerak ke arah atas kotak (ular utama bergerak ke arah kanan). The c
cek ular bahwa sel grid saat ini adalah 0
dan bahwa setiap sel di atas itu adalah spasi. Jika gagal, seluruh pertandingan gagal. Jika berhasil, kami melanjutkan
{c<R>}
yang melakukan hal yang sama, hanya berbelok ke kanan (menuju bagian bawah kotak).
Perhatikan bahwa spawn ini tidak mempengaruhi posisi pointer pertandingan di ular utama. Mereka agak mirip lookaheads di regex. (Mungkin di sini kita dapat memanggil mereka "lookbesides"?) Jadi setelah memverifikasi bahwa kita menunjuk ke 0
dan kolom lainnya hanya berisi spasi, kita harus benar-benar mencocokkan 0
:
0
Sekarang pointer pertandingan ada pada karakter di sebelah kanan 0
. Kita perlu memeriksa tiga opsi berbeda: sudut ular turun, sudut ular naik, atau ular lurus. Untuk ini, kita dapat menggunakan ekspresi ATAU:
[...]
Di dalam OR kami, kami memiliki tiga kemungkinan:
(<R> <L>)
Belok kanan, cocok dengan spasi, dan belok kiri lagi (sudut ular turun).
(<L> <R>)
Belok kiri, cocokkan spasi, dan belok kanan lagi (sudut ular naik).
_?
Cocokkan dengan nol atau satu garis bawah. Karena tidak ada garis bawah pada input, ini akan selalu menjadi pertandingan kosong (ular lurus).
Setelah mencocokkan salah satu dari tiga opsi di atas, pointer pencocokan harus menunjuk ke 0
dalam kolom berikutnya, siap untuk mencocokkan lagi dengan tanda kurung.