Cubix, 94 83 82 79 63 56 bajtów
p>q'-?w.uh'e@U7.'hqi?oqB-!ul.-..$WWu_q<o'\;>....6t?.../!@
Rozszerzony:
p > q '
- ? w .
u h ' e
@ U 7 .
' h q i ? o q B - ! u l . - . .
$ W W u _ q < o ' \ ; > . . . .
6 t ? . . . / ! @ . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Notatki
- Interpretator wyłącza pole wprowadzania podczas uruchamiania programu. W związku z tym nieskończony strumień danych wejściowych jest niemożliwy. Ten program pobiera dane wejściowe znak po znaku, więc gdyby nie to ograniczenie, działałoby poprawnie.
- Ten program nie usuwa stosu i bardzo szybko się psuje. Ponieważ maszyna, która zostanie użyta, najwyraźniej może dawać nieskończone strumienie wejściowe, rozsądne wydaje się założenie, że ma ona również nieskończoną pamięć.
- Każda pomoc golfa jest bardzo ceniona.
Wypróbuj online
Możesz wypróbować program tutaj .
Wyjaśnienie
Główny pomysł
Ogólna idea polega na tym, że chcemy odczytać znak, a następnie porównać go z różnymi znakami (najpierw h, potem epoteml itd.). Aby śledzić postać, którą przegapiliśmy, trzymamy ją na samym dole stosu. Kiedy go potrzebujemy, możemy z łatwością przenieść go na szczyt.
Pętla odczytu / zapisu
Pętla do odczytu i zapisu jest po prostu piątą linią. Wszystkie nieużywane znaki są zastępowane przez no-ops ( .):
. . . .
. . . .
. . . .
@ . . .
' h q i ? o q B - ! u l . - . .
. . . . _ . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Można to podzielić na dwie części: czytanie i (pisanie i sprawdzanie). Pierwsza część zawiera instrukcje do znaku zapytania włącznie. Druga część w górę to reszta linii. Ponieważ to się zapętla, zakładamy, że zaczynamy od stosu[...]
@
'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
Druga część (pisanie i sprawdzanie) jest znowu liniowa. Stos zaczyna się jako [next-char, ..., input]. Wyodrębniliśmy kolejny znak, ponieważ zmienia się on później w programie.
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.
Teraz IP zacznie się ponownie na początku tej pętli, resetując następny znak do sprawdzenia h.
Dopasowywanie następnego znaku
Jeśli adres IP wykonał zwrot (tj. Znak, który przeczytaliśmy i wydrukowaliśmy, pasował do następnego znaku 'hello'), musimy sprawdzić, jaki znak był wejściem i, zależnie od tego, przesunąć następny znak na dół stosu. Następnie musimy powrócić do pętli odczytu / zapisu bez pchania hdo stosu, więc potrzebujemy innego sposobu, aby się tam dostać.
Po pierwsze: określ, jaki znak był wprowadzony. Stos wygląda tak: [..., prev-char, input, 0].
. . . .
- ? . .
u h ' e
. . . .
. . . . . . . . . ! u . . . . .
. . . . . . . . . \ ; . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Aby porównać dane wejściowe, ponownie użyjemy kodu znakowego h. Początkowo było tak, ponieważ tak naprawdę nie wiedziałem, jak sobie z tym poradzić i hjest to pierwszy znak w ciągu, który można sprawdzić, ale okazało się to dość wygodne. Jeśli odejmiemy kod znakowy h od danych wejściowych, otrzymamy, -3jeśli dane wejściowe są e, 0jeśli dane wejściowe są h, 4jeśli dane wejściowe są li 7jeśli dane wejściowe są o.
Jest to przydatne, ponieważ ?polecenie pozwala nam łatwo oddzielić wartości ujemne od wartości dodatnich od zera. Jako taki, jeśli IP skręca w lewo, różnica była ujemna, więc wejście było e, więc następny znak powinien być l. Jeśli adres IP kontynuuje prostą różnicę, różnica była 0, więc wejście było h, więc następnym znakiem powinien być znak e. Jeśli dane wejściowe to an llub ano , adres IP skręca w prawo.
Wszystkie instrukcje wykonane przed wspomnianym znakiem zapytania to:
;!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]
Teraz adres IP zmienia swój kierunek, jak opisano powyżej. Omówmy różne możliwości.
Wkład 'e'
Najpierw rozważymy dane wejściowe e, które powodują przesunięcie adresu IP w górę od ?, ponieważ różnica wynosi 3. Wszystkie nieistotne znaki zostały usunięte z kostki.
. > q '
. ? . .
. . . .
. . . .
. . q . . . . . . . . l . . . .
$ W W . . . . . . . . > . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Znaki są wykonywane w tej kolejności (z wyłączeniem niektórych znaków przepływu kontrolnego):
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, ...]
Teraz adres IP ponownie osiągnął pętlę odczytu / zapisu.
Wkład 'h'
Jeśli wejście było 'h', różnica wynosi 0, więc adres IP nie zmienia swojego kierunku. Oto znowu kostka, z usuniętymi wszystkimi nieistotnymi postaciami. Ponieważ ta ścieżka zawiera sporo no-opów, wszystkie przejrzane przez nią no-ops zostały zastąpione &. Adres IP zaczyna się od znaku zapytania.
. . . .
. ? w .
. . ' e
. . . .
. . . . . . . . . ! . . . . . .
. . . u _ q < . . \ . . . . . .
. . ? & & & / . . & . . . . . .
. . & . . . . . . & . . . . . .
. . . .
& & & &
. . . .
. . . .
Wykonywane instrukcje to:
'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
A teraz znów wchodzimy w pętlę odczytu / zapisu, więc gotowe.
Inne dane wejściowe
Wszystkie pozostałe dane wejściowe powodują różnicę dodatnią, więc adres IP skręca w prawo przy znaku zapytania. Nadal musimy oddzielić li o, więc to zrobimy dalej.
Oddzielając 'l'i'o'
Należy pamiętać, że różnica wynosi 7 dla oi 4 dla li że musimy zakończyć program, jeśli dane wejściowe to o. Oto znowu sześcian z nieistotnymi częściami zastąpionymi przez a, .a no-ops krzyże IP zostały zastąpione znakami ampersands.
. . 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
Rozróżnianie między nimi 'l' s
Teraz wiemy, że dane wejściowe były l, ale nie wiemy, który l. Jeśli jest to pierwszy, musimy przesunąć kolejny lna spód stosu, ale jeśli jest to drugi, musimy przesunąć o. Pamiętasz, jak zapisaliśmy -3się na dole stosu tuż przed wypchnięciem pierwszego l? Możemy to wykorzystać do rozdzielenia dwóch gałęzi.
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
6 t ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Stos zaczyna się jako [..., -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
Pierwszy 'l'
Jeśli to był pierwszy 'l', musimy wcisnąć kolejny 'l'. Aby zapisać bajty, używamy tych samych znaków, co dla pierwszego 'l'. Możemy uprościć stos do[...] . Oto odpowiednia część kostki, bez przestojów zastąpionych znakami ampersands.
p > q '
. . . .
. . . .
. . . .
' . q . . . . . . . . l . . . .
$ W W . . . . . . . . > & & & &
. . ? . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
Wykonywane są następujące instrukcje:
$'pq'lq
$' no-op
pq no-op
'l Push the character code of l
Stack: [..., 108]
q Send it to the bottom
Stack: [108, ...]
Wkrótce przejdziemy do pętli odczytu / zapisu, więc skończyliśmy z tą gałęzią.
druga 'l'
Jeśli wejście był drugim 'l'w 'hello', IP skręcił w prawo na znak zapytania. Po raz kolejny możemy uprościć stos, [...]a adres IP zaczyna się od ?, wskazując tym razem na południe.
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . . . . . . .
. . . u _ q < o ' \ . . . . . .
. . ? . . . . . . & . . . . . .
. . & . . . . . . & . . . . . .
. . . .
& & & &
. . . .
. . . .
Wykonywane instrukcje to:
'oq_
'o Push the character code of 'o'
Stack: [..., 111]
q Move the top item to the bottom
Stack: [111, ...]
_ No-op
I adres IP niedługo wejdzie w pętlę odczytu / zapisu, więc skończyliśmy również z tą gałęzią.