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 e
poteml
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 h
do 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 h
jest 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, -3
jeśli dane wejściowe są e
, 0
jeśli dane wejściowe są h
, 4
jeśli dane wejściowe są l
i 7
jeś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 l
lub 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ć l
i o
, więc to zrobimy dalej.
Oddzielając 'l'
i'o'
Należy pamiętać, że różnica wynosi 7 dla o
i 4 dla l
i ż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 l
na spód stosu, ale jeśli jest to drugi, musimy przesunąć o
. Pamiętasz, jak zapisaliśmy -3
się 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ą.