Це, очевидно, правильна мова для завдання. : ^ D
s:({c<L>}{c<R>}0[(<R> <L>)(<L> <R>)_?])%{30}
c:0 *$
Відповідає всьому входу, якщо це дійсна змія; не відповідає, якщо це не так. Спробуйте тут!
Пояснення
SnakeEx - це дводенна мова відповідності зразком . Програма складається зі списку визначень для "змій", які повзають навколо вхідних відповідних символів, змінюючи напрямки та нерестують інших змій. У нашій програмі ми визначаємо дві змії s
та c
.
Почнемо з того, c
що це простіше. Його визначення таке 0 *$
, що має бути цілком читабельним, якщо ви знаєте регулярний вираз: match 0
, з наступним нулем або більше пробілів, а потім край сітки. Основний улов тут: це узгодження може тривати в будь-якому напрямку. Ми будемо використовувати c
як змія вгору, так і вниз, щоб перевірити, чи немає 0
в кожному стовпчику зайвих с.
Тепер про головну змію , s
. Він приймає форму (...)%{30}
, що означає "відповідати змісту дужок 30 разів" - один раз для кожного 0
в змії. Все йде нормально. Що йде всередині дужок?
{c<L>}
Це породить нову c
змію, повернуту ліворуч на 90 градусів. Напрямок відносно напрямку s
змії, тому нова змія рухається у верхній частині сітки (головна змія рухається вправо). У c
змії перевіряє , що поточна комірка сітки являє собою 0
і що кожна клітина над ним простір. Якщо він не вдається, весь матч виходить з ладу. Якщо це вдасться, ми продовжуємо с
{c<R>}
що робить те саме, тільки повернуто праворуч (у напрямку до нижньої частини сітки).
Зауважте, що ці нерести не впливають на положення вказівника сірника в основній змії. Вони трохи схожі на лукаголовки в регексе. (Може, тут ми могли б назвати їх "lookbesides"?) Тож після перевірки того, що ми вказуємо на a, 0
а решта стовпця містить лише пробіли, нам потрібно насправді відповідати 0
:
0
Тепер покажчик відповідності знаходиться на символі праворуч від поля 0
. Нам потрібно перевірити три різні варіанти: кути змії вниз, змії кути вгору або змія йде прямо. Для цього ми можемо використовувати вираз АБО:
[...]
Всередині нашого АБО є три можливості:
(<R> <L>)
Поверніть праворуч, сумістіть пробіл і знову поверніть ліворуч (зміїні кути вниз).
(<L> <R>)
Поверніть ліворуч, сумістіть пробіл і знову поверніть праворуч (зміїні кути вгору).
_?
Зрівняти нуль або один підкреслення. Оскільки у введенні немає підкреслень, це завжди буде порожнім збігом (змія йде прямо).
Після відповідності одному з перерахованих вище трьох варіантів вказівник відповідності повинен вказувати на 0
наступний стовпець, готовий знову відповідати викладеному в дужці виразом.