Cubix, 94 83 82 79 63 56 байт
p>q'-?w.uh'e@U7.'hqi?oqB-!ul.-..$WWu_q<o'\;>....6t?.../!@
Expanded:
p > q '
- ? w .
u h ' e
@ U 7 .
' h q i ? o q B - ! u l . - . .
$ W W u _ q < o ' \ ; > . . . .
6 t ? . . . / ! @ . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Заметки
- Интерпретатор отключает поле ввода при запуске программы. Таким образом, бесконечный поток ввода невозможен. Эта программа принимает ввод за символом, поэтому, если бы не это ограничение, оно работало бы правильно.
- Эта программа не очищает стек, и она очень быстро запутывается. Поскольку машина, на которой это будет использоваться, по-видимому, может давать бесконечные входные потоки, разумно предположить, что она также имеет бесконечную память.
- Любая помощь в гольф очень ценится.
Попробуйте онлайн
Вы можете попробовать программу здесь .
объяснение
Главная идея
Общая идея заключается в том, что мы хотим прочитать символ, а затем проверить его на предмет изменяющихся символов (сначала h
, затем e
, затем l
и т. Д.). Чтобы отслеживать пропущенного персонажа, мы держим его в самом низу стека. Когда нам это нужно, мы легко можем снова поднять его на вершину.
Цикл чтения / записи
Цикл чтения-записи - это просто 5- я строка. Все неиспользуемые символы заменяются на no-ops ( .
):
. . . .
. . . .
. . . .
@ . . .
' h q i ? o q B - ! u l . - . .
. . . . _ . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Это можно разделить на две части: чтение и (написание и проверка). Первая часть содержит инструкции вплоть до знака вопроса. Вторая часть - это остальная часть строки. Поскольку это зацикливается, мы предполагаем, что мы начинаем со стека[...]
@
'hqi?
_
Explanation
'h Push the character code of the h
Stack: [..., 104]
q Send it to the bottom
Stack: [104, ...]
i Read one character of the input (-1 for EOF)
Stack: [104, ..., input]
? Start of condition:
if (input < 0):
@ execute '@', ending the program
if (input = 0):
continue going right
if (input > 0):
_ turn to the right, reflect back ('_') and
turn right again, effectively not changing
the direction at all
Вторая часть (написание и проверка) снова линейна. Стек начинается как [next-char, ..., input]
. Мы абстрагировали следующий символ, потому что это меняется позже в программе.
oqB-!ul.- Explanation
o Output the character at the top of the stack
q Send the input to the bottom of the stack
Stack: [input, next-char, ...]
B Reverse the stack
Stack: [..., next-char, input]
- Push the difference of the top two characters, which
is 0 if both are equal, something else otherwise
Stack: [..., next-char, input, diff]
! if (diff = 0):
u make a u-turn to the right
else:
l. execute two no-ops
- push [input - next-char - input], which is disregarded
later, so it effectively is a no-op as well.
Теперь, IP начнется снова в начале этого цикла, сбрасывая следующий символ для проверки h
.
Соответствие следующему персонажу
Если IP сделал разворот (т. Е. Символ, который мы прочитали и напечатали, соответствовал следующему символу 'hello'
), нам нужно проверить, каким символом был ввод, и в зависимости от этого сдвинуть следующий символ в конец стека. После этого нам нужно вернуться к циклу чтения / записи, не помещая h
его в стек, поэтому нам нужен другой способ попасть туда.
Перво-наперво: определите, каким персонажем был ввод. Стек выглядит следующим образом : [..., prev-char, input, 0]
.
. . . .
- ? . .
u h ' e
. . . .
. . . . . . . . . ! u . . . . .
. . . . . . . . . \ ; . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Чтобы сравнить ввод, мы h
снова используем код символа . Первоначально это было потому, что я не знал, как я собираюсь с этим справиться, и h
это первый символ в строке, который нужно проверить, но в итоге это оказалось довольно удобным. Если мы вычтем код символа h из ввода, мы получим, -3
если вход есть e
, 0
если вход есть h
, 4
если вход l
и 7
если вход o
.
Это полезно, потому что ?
команда позволяет нам легко отделить отрицательные значения от положительных значений и нуля. Таким образом, если IP поворачивается влево, разница была отрицательной, поэтому ввод был e
, поэтому следующий символ должен быть l
. Если IP продолжает идти прямо, разница была 0
, поэтому ввод был h
, поэтому следующий символ должен быть e
. Если вход является l
или o
, IP поворачивается направо.
Все инструкции, выполненные до вышеупомянутого знака вопроса:
;!e'h- Explanation
; Delete the top of the stack
Stack: [..., prev-char, input]
! if (input = 0):
e execute 'e' (no-op)
'h Push the character code of h
Stack: [..., prev-char, input, 104]
- Push the difference of the input and 104
Stack: [..., prev-char, input, 104, diff]
Теперь IP меняет свое направление, как описано выше. Давайте рассмотрим различные возможности.
вход 'e'
Сначала мы рассмотрим ввод e
, который заставляет IP двигаться вверх от ?
, так как разница равна 3. Все нерелевантные символы были удалены из куба.
. > q '
. ? . .
. . . .
. . . .
. . q . . . . . . . . l . . . .
$ W W . . . . . . . . > . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Символы выполняются в следующем порядке (исключая некоторые символы потока управления):
q'l$WWq
q Save the difference (-3) to the bottom of the stack so
we can tell whether the l on the bottom of the stack is
the first or the second l in hello
Stack: [-3, ...]
'l Push the character code of l to the stack
Stack: [-3, ..., 108]
$W no-op
W Sidestep into the loop
q Send the character code to the bottom
Stack: [108, -3, ...]
Теперь IP снова достиг цикла чтения / записи.
вход 'h'
Если вход был 'h'
, разница равна 0, поэтому IP не меняет своего направления. Снова куб, со всеми не относящимися к делу персонажами. Поскольку этот путь включает в себя довольно много неактивных операций, все пропущенные им операции были заменены &
. IP начинается с вопросительного знака.
. . . .
. ? w .
. . ' e
. . . .
. . . . . . . . . ! . . . . . .
. . . u _ q < . . \ . . . . . .
. . ? & & & / . . & . . . . . .
. . & . . . . . . & . . . . . .
. . . .
& & & &
. . . .
. . . .
Выполненные инструкции:
'e!\?q_
'e Push the character code of the e
Stack: [..., 101]
! if (101 = 0):
\ reflect away (effectively a no-op)
? if (101 > 0):
turn right (always happens)
q Move 101 to the bottom of the stack
Stack: [101, ...]
_ No-op
И теперь мы снова входим в цикл чтения / записи, так что мы закончили.
Другие входы
Все остальные входные данные приводят к положительной разнице, поэтому IP-адрес поворачивается направо на вопросительный знак. Нам все еще нужно разделить l
и o
то, что мы будем делать дальше.
Разделение 'l'
и'o'
Имейте в виду, что разница составляет 7 для o
и 4 для l
и что мы должны завершить программу, если ввод был o
. Вот куб снова с нерелевантными частями, замененными на a, .
и нет-опы, кресты IP были заменены амперсандами.
. . q .
. ? w .
. h ' .
. U 7 .
. . . . . . . . . . . . . - . .
. . . . . . . . . . . . . & . .
. . . . . . / ! @ . . . . & . .
. . . . . . & . . . . . . & . .
. . & .
. . & .
. . & .
. . & .
h7'wq-!@
h no-op
7 Push 7 to the stack
Stack: [..., diff, 7]
'wq Push w to the stack and send it to
the bottom. We don't care about it,
so it's now part of the ellipsis.
Stack: [..., diff, 7]
-! if (diff = 7):
@ End the program
Различение между этими двумя 'l'
с
Итак, теперь мы знаем, что вклад был l
, но мы не знаем, какой l
. Если это первое, нам нужно подтолкнуть другого l
к нижней части стека, но если это второе, нам нужно подтолкнуть o
. Помните, мы сохранили -3
в конец стека как раз перед тем, как выдвинуть первый l
? Мы можем использовать это для разделения двух ветвей.
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
6 t ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Стек начинается как [..., -3 or 140, ...]
Explanation
6t?
6t Take the 6th item from the top and move
it to the top (which is either -3 or 140)
? If that's positive, turn right, otherwise,
turn left
Первый 'l'
Если это было первым 'l'
, нам нужно подтолкнуть другого 'l'
. Для сохранения байтов мы используем те же символы, что и для первого 'l'
. Мы можем упростить стек до [...]
. Вот соответствующая часть куба, где нет операций, замененных амперсандами.
p > q '
. . . .
. . . .
. . . .
' . q . . . . . . . . l . . . .
$ W W . . . . . . . . > & & & &
. . ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Следующие инструкции выполняются:
$'pq'lq
$' no-op
pq no-op
'l Push the character code of l
Stack: [..., 108]
q Send it to the bottom
Stack: [108, ...]
Мы собираемся войти в цикл чтения / записи, поэтому мы закончили с этой веткой.
второй 'l'
Если вход был вторым 'l'
в 'hello'
, то IP повернул направо на знак вопроса. Еще раз, мы можем упростить стек, [...]
и IP начинается с, на ?
этот раз, указывая на юг.
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . .
. . . u _ q < o ' \ . . . . . .
. . ? . . . . . . & . . . . . .
. . & . . . . . . & . . . . . .
. . . .
& & & &
. . . .
. . . .
Выполненные инструкции:
'oq_
'o Push the character code of 'o'
Stack: [..., 111]
q Move the top item to the bottom
Stack: [111, ...]
_ No-op
И IP собирается снова войти в цикл чтения / записи, так что мы закончили и с этой веткой.