Це, очевидно, правильна мова для завдання. : ^ 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наступний стовпець, готовий знову відповідати викладеному в дужці виразом.