Я с гордостью представляю ...
<}74}}:23}29}59}}}}}}}:111_}}}}:::::::23_}:111
? @
:" }}_47}_95 3""""""""(
_ : } _ } {=}
2 23_}29_ _ ; : \
0 ; 3 +_( 3_" 60{ .{.{.
"-_95:}}"" 2 0 ) 2 " _ _ {
"" _ : 2 _ ."(; } 3 .{
;_92}_47} : _ 0 = : * ;
: "" 2 {.{{ . -""(
}}:59_}}:::: "";_ . { _ "
} " {.{.{. 32.
}}}_95:}}}}_20-
... мой новый двухмерный лабиринт esolang! Приведенный выше код не очень хорошо подходит для игры в гольф (есть 161 пробел и 25 NOP, поэтому лучшая компоновка может значительно сократить это), но, по крайней мере, мне удалось показать, что язык пригоден для нетривиальных задач. :)
Как это работает
Сначала краткий обзор языка:
- Лабиринт работает на два стека, основной и вспомогательный , которые могут содержать произвольные целые числа со знаком. В нижней части обоих стеков есть бесконечное количество нулей.
- Команды - это отдельные символы в двумерной сетке, и они образуют лабиринт (то есть неизвестные символы, особенно пробелы, являются стенами).
"
это NOP, который не является стеной и может быть полезен для заполнения определенных путей в коде. В отличие от многих других 2D-языков, края не смещаются.
- Указатель инструкций (IP) начинается с первого нестрочного символа (в порядке чтения), перемещающегося вправо.
@
завершает программу
- Если возможно, IP следует по коридорам (также вокруг поворотов). Если IP имеет несколько ячеек для перемещения, он обычно поворачивает налево, если вершина основного стека отрицательна, перемещается прямо вперед, если он равен нулю, или поворачивает направо, если он положительный. Когда IP попадает в стену, он меняет направление. (Есть еще несколько тонкостей, но они не должны иметь значения для этого кода.) Это единственный способ реализовать поток управления.
- Помимо арифметических и стековых команд, исходный код может быть изменен во время выполнения с помощью четырех команд,
>v<^
которые циклически сдвигают строку или столбец исходного кода на одну ячейку. Какая строка или столбец зависит от вершины стека. Если собственная строка или столбец IP смещены, они будут перемещаться вместе со смещением. Это позволяет перейти с одного края исходного кода на другой.
Теперь для этой конкретной задачи, вот общая идея алгоритма:
- Наденьте концы вагонов на крышки (т. Е.
/ \_o oo o
) На вспомогательный стек.
- Прочитайте ввод и определите, нужно ли нажимать
__
или /\
дальше.
- Вставьте оставшуюся часть машин (то есть
__ __ _/ \
и два ведущих пространства) на вспомогательный стек.
- Зафиксируйте вход до максимального значения
20
, давайте назовем это N .
- Теперь сделайте следующее 3 раза:
- Распечатать N пробелов.
- Напечатайте 6 сохраненных символов.
- Печать 60 - 3 * N пробелов.
- Напечатайте 6 сохраненных символов.
- Распечатать новую строку.
Наконец, давайте посмотрим на некоторые части кода. IP начинается в верхнем левом углу команды сдвига сетки. Вершина основного стека 0
(которая используется как относительный индекс), поэтому первая строка смещена влево, что также перемещает IP-адрес в правый конец сетки. Теперь первая строка просто выполняется справа налево, что помещает первый набор фиксированных символов во вспомогательный стек:
}74}}:23}29}59}}}}}}}:111_}}}}:::::::23_}:111<
Это смещение строк полезно для игры в гольф, когда вы хотите начать с большого количества линейного кода.
Далее мы читаем ввод и нажимаем правильные крышки:
?
:"
_
2
0 ;
"-_95:}}""
"" _
;_92}_47}
Бит слева с тремя NOP отправляет отрицательные результаты по верхней ветви и неотрицательные результаты по нижней ветви. Справа они соединены вместе.
Теперь следует еще один большой линейный участок (который, вероятно, можно было бы много сыграть с помощью другого трюка со сдвигом строк):
}}_47}_95
: }
23_}29_ _
3
2
:
:
:
}}:59_}}::::
}
}}}_95:}}}}
Это толкает оставшуюся часть машин на вспомогательный стек.
Далее мы вычисляем min(20, input)
, что похоже на первую ветку:
;
+_(
0 )
2 _
_ 0
"" 2
"";_
"
_20-
Наконец, у нас есть цикл, который запускается три раза для печати строк. Каждая итерация цикла содержит два маленьких (3x3) цикла для печати пробелов, а также два раздела для печати 6 символов из вспомогательного стека:
@
3""""""""(
_ } {=}
: \
3_" 60{ .{.{.
2 " _ _ {
."(; } 3 .{
= : * ;
{.{{ . -""(
. { _ "
{.{.{. 32.
Один изящный трюк, на который я хотел бы обратить внимание - .{.{.
это правый край. Это тупик, поэтому, кроме .
конца, код выполняется дважды, один раз вперед и один раз назад. Это дает аккуратный способ сократить палиндромный код (выгода заключается в том, что вам нужно убедиться, что IP-адрес принимает правильный поворот при выходе из тупика снова).
/ \
а не опущены_ _
?