_8
,%
;
"}{{+_5
"= %_!
= """{
;"{" )!
Завершается ошибкой деления на ноль (сообщение об ошибке в STDERR).
Попробуйте онлайн!
Расположение кажется действительно неэффективным, но я просто не вижу способа играть в гольф прямо сейчас.
объяснение
Это решение основано на арифметическом приеме Денниса: возьмите все коды символов по модулю 8
, добавьте пару с обоих концов и убедитесь, что она делится на 5
.
Лабиринтный праймер:
- Лабиринт имеет два набора целых чисел произвольной точности, main и aux (ily), которые изначально заполнены (неявным) бесконечным количеством нулей.
- Исходный код напоминает лабиринт, где указатель инструкций (IP) следует за коридорами, когда это возможно (даже за углами). Код начинается с первого действительного символа в порядке чтения, то есть в этом случае в верхнем левом углу. Когда IP-адрес достигает какой-либо формы соединения (то есть нескольких соседних ячеек в дополнение к той, из которой он получен), он выбирает направление на основе вершины основного стека. Основные правила: поверните налево при отрицательном значении, продолжайте движение вперед при нулевом, поверните направо при положительном. И когда один из них невозможен из-за наличия стены, тогда IP будет идти в противоположном направлении. IP также оборачивается при попадании в тупик.
- Цифры обрабатываются путем умножения вершины основного стека на 10 и последующего добавления цифры.
Код начинается с небольшого цикла 2x2 по часовой стрелке, который читает все входные данные по модулю 8:
_ Push a 0.
8 Turn into 8.
% Modulo. The last three commands do nothing on the first iteration
and will take the last character code modulo 8 on further iterations.
, Read a character from STDIN or -1 at EOF. At EOF we will leave loop.
Сейчас ;
сбрасывает -1
. Мы вводим еще один цикл по часовой стрелке, который перемещает верхнюю часть основного стека (т.е. последний символ) вниз:
" No-op, does nothing.
} Move top of the stack over to aux. If it was at the bottom of the stack
this will expose a zero underneath and we leave the loop.
= Swap top of main with top of aux. The effect of the last two commands
together is to move the second-to-top stack element from main to aux.
" No-op.
Теперь есть короткий линейный бит:
{{ Pull two characters from aux to main, i.e. the first and last (remaining)
characters of the input (mod 8).
+ Add them.
_5 Push 5.
% Modulo.
Теперь IP находится на стыке, который действует как ветвь для проверки делимости на 5. Если результат по модулю не равен нулю, мы знаем, что входной сигнал не является палиндромом Уотсона-Крика, и мы поворачиваем на восток:
_ Push 0.
! Print it. The IP hits a dead end and turns around.
_ Push 0.
% Try to take modulo, but division by zero fails and the program terminates.
В противном случае мы должны продолжать проверять оставшуюся часть ввода, чтобы IP продолжал двигаться на юг. В {
тянет за нижнюю часть оставшегося входа. Если мы исчерпали ввод, то это будет 0
(снизу aux ), и IP продолжает двигаться на юг:
) Increment 0 to 1.
! Print it. The IP hits a dead end and turns around.
) Increment 0 to 1.
{ Pull a zero over from aux, IP keeps moving north.
% Try to take modulo, but division by zero fails and the program terminates.
В противном случае в строке будет проверено больше символов. IP поворачивается на запад и переходит в следующий (по часовой стрелке) цикл 2x2, который в основном состоит из no-ops:
" No-op.
" No-op.
{ Pull one value over from aux. If it's the bottom of aux, this will be
zero and the IP will leave the loop eastward.
" No-op.
После этого цикла мы снова получаем ввод в основной стек, за исключением его первого и последнего символа и с нулем сверху. В ;
отбрасывает , 0
а затем =
меняет местами вершины стеков, но это просто отменить первое =
в цикле, потому что мы вступаем в цикл в другом месте. Промыть и повторить.