Эта задача является призом для ais523 за победу в категории « Новичок года » в номинации « Лучший из PPCG 2016 ». Поздравляем!
BackFlip - это эзотерический язык программирования, созданный пользователем ais523 , который создал более 30 других интересных эзолангов .
BackFlip это 2D-язык, как Befunge или > <>, где указатель инструкций пересекает сетку текста (программу), перемещаясь вверх, вниз, влево и вправо, изменяя направление в зависимости от символа, на котором он находится. Крайне важно, что сетка в программе BackFlip изменяется по мере прохождения, немного как муравей Лэнгтона .
Для этой задачи вы можете предположить, что программа BackFlip всегда представляет собой прямоугольную сетку текста (все строки одинаковой длины), размером не менее 1 × 1, содержащую только символы ./\<>^V
. ( .
используется для видимости, а не для пробела.) Семантически BackFlip, который мы здесь используем, идентичен оригинальной спецификации .
Указатель инструкций (IP) в BackFlip всегда начинается слева от верхнего левого угла программы, направляясь вправо. Есть три типа команд, с которыми он может столкнуться:
.
это неоперация. IP продолжается в том же направлении, в котором он шел. Без операции остается без операции./
и\
являются зеркалами. Они отражают IP в направлении, указанном их углом, затем они превращаются в зеркало другого типа .- Например, если IP направляется в a
\
, он начинает двигаться вверх, а не влево, и\
становится a/
.
- Например, если IP направляется в a
<
,>
,^
, ИV
являются стрелки. Они перенаправляют IP-адрес в указанном направлении, а затем превращаются в стрелки, указывающие направление, в котором появился IP-адрес (в противоположном направлении от IP-адреса) .- Например, если IP направляется вниз
>
, он начинает двигаться вправо, а не вниз, и>
становится^
так, потому что это направление, откуда пришел IP.
- Например, если IP направляется вниз
Программа BackFlip завершается, когда IP выходит за границы, то есть выходит из сетки. Оказывается, все программы BackFlip в конце концов заканчиваются, потому что бесконечные циклы невозможны. (Вы можете предположить, что это правда.)
Ваша задача в этой задаче состоит в том, чтобы написать программу или функцию, которая принимает программу BackFlip и выводит количество ходов, которые указатель инструкций совершил до завершения программы. То есть, сколько шагов IP делает в ходе работы программы? Это включает в себя начальный шаг в сетке и последний шаг от нее.
Например, указатель инструкции выполняет 5 шагов в тривиальной сетке ....
:
.... <- empty 4×1 grid
012345 <- step number of the IP
Итак, вывод ....
есть 5
.
В более сложной сетке 4 × 2
\...
\.><
IP выходит из сетки на своем 9-м шаге, поэтому вывод 9
:
step grid IP position (@)
0 \... @....
\.>< ....
1 \... @...
\.>< ....
2 /... ....
\.>< @...
3 /... ....
/.>< .@..
4 /... ....
/.>< ..@.
5 /... ....
/.<< ...@
6 /... ....
/.<< ..@.
7 /... ....
/.>< .@..
8 /... ....
/.>< @...
9 /... ....
\.>< ....
@
Самый короткий код в байтах побеждает.
Вы можете принять ввод как массив строк или матрицу символов вместо многострочной строки, если хотите, но вы должны использовать символы ./\<>^V
(не целочисленные коды операций). Вы можете использовать пространство вместо.
если предпочитаете. Это хорошо, если такие символы, как например, \
необходимо экранировать при вводе. Вывод всегда является целым числом больше одного.
Тестовые случаи
....
5
\...
\.><
9
.
2
..
3
.
.
2
\
2
^
2
.^.
3
<.
2
\\
\/
7
>V
^<
6
>\
>/
6
\><
2
\><
\><
7
\><
\><
\><
12
\.V.
\.\<
5
\.V.
\./<
9
V./\
V./\
>./<
..\/
14
\V..
.^..
\/><
.V..
.^..
20
\.V.V.
\./.\<
.>\<..
..^.^.
31
\.V.V.V.
\./>/.\<
.>\>\<..
..^.^.^.
69
\.V.V.V.V.
\./>/>/.\<
.>\>\>\<..
..^.^.^.^.
145
\.V.V.V.V.V.V.V.V.V.V.
\./>/>/>/>/>/>/>/>/.\<
.>\>\>\>\>\>\>\>\>\<..
..^.^.^.^.^.^.^.^.^.^.
9721
источник
/
, IP поднимется, а вверх/
- IP, как если бы мяч отскакивал от стены. (Но помните, что/
изменения коснулись после того, как IP коснулся его.)Ответы:
JavaScript (ES6), 158 байт
Разработано независимо от ответа @ tsh, хотя поразительно похоже.
Сопоставление направлений
^<v>
с целыми числами 0-3 определяется тем, что.search('^')
возвращает 0, поскольку^
является метасимволом регулярного выражения.источник
Хаскелл ,
333325 байтРЕДАКТИРОВАТЬ:
f
точек и объединено вb
.b
берет списокString
s и возвращаетInteger
.Попробуйте онлайн!
Как это устроено
C a
это тип данных, используемый потому, что Haskell не позволит типу быть рекурсивным, не объявив его явно.C
также является конструктором обёртывания иc
его соответствующей функцией распаковки. Используется только сa=[Int]
.C [Int]
представляет команду ячейки как функцию, которая принимает[Int]
аргумент direction ( ) и возвращает пару нового направления и новогоC [Int]
значения.b
это основная функция. Он преобразует каждый символ вC
значение, а затем вызывает#
.g
это сетка в виде списка строк.\
необходимо экранировать и поэтому это самый длинный символ, который нужно упомянуть, его результат вместо этого используется в качестве значения по умолчанию для поиска в списке.#
запускает основное моделирование, проверяет границы&
и генерирует новые сетки с?
.[y,x]
текущая позиция,d
текущее направление иg
текущая сетка.[f,e]
является следующим направлением иn
является его парой и следующей сеткой.l&i
проверяет, находится ли индексi
за пределами спискаl
. (ВозвращаетсяTrue
за пределы, поскольку это позволяет избежать фиктивного состояния охраны в#
.)f(l!!i)==(d,x)
,(f?i)l==(d,m)
гдеm
находится списокl
сi
замененным элементом th наx
.(?i)
это более общий объектив, фокусирующийся на i-м элементе списка, в данном случае используемый с(,) [Int]
экземпляром функтора.n
это функция, представляющая точку.a v
это функция , представляющая стрелу в направленииv
.m s
является функцией, представляющей зеркало;s==1
для\\
иs==-1
для/
.источник
JavaScript, 172 байта
Но я не могу проверить последний тестовый пример, так как у меня переполнение стека на моей машине. (должен работать, если есть машина с большим оперативной памятью)
Мы используем номер для направления:
Позвольте
d
быть номером направления ...Пусть
(x, y)
будет текущее положение, следующее положение:x+(t&1&&t-2)
,y+(~t&1&&t-1)
Замечания:
Функция принимает один параметр в следующем формате:
Проверьте это здесь
источник
Uncaught RangeError: Maximum call stack size exceeded
с 16 ГБ оперативной памяти.var
объявления заставляют его пройти последнийC
232221 байтПринимает ввод в первом аргументе, печатает результат. Требуется, чтобы ввод содержал как минимум 1 символ новой строки (поэтому, если есть только 1 строка, он должен заканчиваться символом новой строки)
Пример использования:
Сломать:
источник
Python 3 , 286 байт
[f () принимает входные данные в виде
{(0,0):'/',(0,1):'.'}
поэтому я также написал функцию g () для преобразования массива строк в эту форму]Попробуйте онлайн!
источник