Cubix, 94 83 82 79 63 56 байт
p>q'-?w.uh'e@U7.'hqi?oqB-!ul.-..$WWu_q<o'\;>....6t?.../!@
Розширено:
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, тому наступним символом має бути an l. Якщо IP продовжує йти прямо, різниця була 0, тому введення було h, тому наступним символом має бути an 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]
Тепер ІС змінює свій напрямок, як детально описано вище. Перейдемо до різних можливостей.
Вхідні дані '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і що ми повинні закінчити програму, якщо введення було an o. Ось куб знову з невідповідними частинами, заміненими на .а, без опор, 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 збирається знову ввести цикл читання / запису, тому ми також закінчили цю гілку.