Это, очевидно, правильный язык для задачи. : ^ D
s:({c<L>}{c<R>}0[(<R> <L>)(<L> <R>)_?])%{30}
c:0 *$
Соответствует всему вводу, если это допустимая змея; не соответствует, если это не так. Попробуй это здесь!
объяснение
SnakeEx - это двумерный язык сопоставления с образцом . Программа состоит из списка определений «змей», которые ползут по вводимым совпадающим символам, меняют направления и порождают других змей. В нашей программе мы определяем двух змей, s
и c
.
Начнем с c
того, что проще. Это определение 0 *$
, которое должно быть вполне читабельным, если вы знаете регулярное выражение: match 0
, за которым следует ноль или более пробелов, за которыми следует край сетки. Основной улов здесь: это сопоставление может продолжаться в любом направлении. Мы будем использовать c
как змею вверх, так и вниз, чтобы убедиться, что 0
в каждом столбце нет лишних s.
Теперь для главной змеи, s
. Он принимает форму (...)%{30}
, что означает «сопоставить содержимое скобок 30 раз» - один раз для каждого 0
в змее. Все идет нормально. Что входит в круглые скобки?
{c<L>}
Это порождает новый c
змею, повернутую влево на 90 градусов. Направление относительно направления s
змеи, поэтому новая змея движется к вершине сетки (главная змея движется вправо). В c
змее проверяет , что текущая ячейка сетки представляет собой 0
и что каждая клетка над ним пространство. Если это не удается, весь матч не удается. Если это удастся, мы продолжим с
{c<R>}
который делает то же самое, только повернул направо (к нижней части сетки).
Обратите внимание, что эти порождения не влияют на положение указателя совпадения в главной змее. Они немного похожи на взглядов в регулярных выражениях. (Может быть, здесь мы могли бы назвать их «lookb Кроме»?) Итак, после проверки, что мы указываем на0
а остальная часть столбца содержит только пробелы, нам нужно на самом деле соответствовать 0
:
0
Теперь указатель совпадения находится на символе справа от 0
. Нам нужно проверить три разных варианта: змея наклонена вниз, змея наклонена вверх, или змея идет прямо. Для этого мы можем использовать выражение OR:
[...]
Внутри нашего OR у нас есть три возможности:
(<R> <L>)
Поверните направо, найдите пробел и снова поверните налево (углы змеи вниз).
(<L> <R>)
Поверните налево, найдите пробел и снова поверните направо (змея наклонена вверх).
_?
Совпадение ноль или подчеркивание. Поскольку на входе нет подчеркиваний, это всегда будет пустое совпадение (змея идет прямо).
После сопоставления с одним из трех приведенных выше вариантов указатель совпадения должен указывать на 0
следующий столбец, готовый снова сопоставить выражение в скобках.