_8
,%
;
"}{{+_5
"= %_!
= """{
;"{" )!
Kończy się z błędem dzielenia przez zero (komunikat o błędzie na STDERR).
Wypróbuj online!
Układ wydaje się naprawdę nieefektywny, ale po prostu nie widzę teraz sposobu na grę w golfa.
Wyjaśnienie
To rozwiązanie opiera się na sztuczce arytmetycznej Dennisa: weź wszystkie kody znaków modulo 8
, dodaj parę z obu końców i upewnij się, że jest podzielna przez5
.
Podkład labiryntowy:
- Labirynt ma dwa stosy liczb całkowitych o dowolnej precyzji, główny i pomocniczy (iliary), które są początkowo wypełnione (domyślną) nieskończoną liczbą zer.
- Kod źródłowy przypomina labirynt, w którym wskaźnik instrukcji (IP) podąża za korytarzami, kiedy może (nawet wokół rogów). Kod zaczyna się od pierwszego poprawnego znaku w kolejności czytania, tj. W tym przypadku w lewym górnym rogu. Kiedy IP dojdzie do dowolnej formy połączenia (tj. Kilku sąsiednich komórek oprócz tej, z której pochodzi), wybierze kierunek w oparciu o górę głównego stosu. Podstawowe zasady to: skręć w lewo, gdy wartość jest ujemna, idź naprzód, gdy zero, skręć w prawo, gdy wartość dodatnia. A jeśli jeden z nich nie jest możliwy, ponieważ istnieje ściana, wówczas IP przyjmie przeciwny kierunek. IP zmienia się również po trafieniu w ślepe zaułki.
- Cyfry są przetwarzane przez pomnożenie górnej części głównego stosu przez 10, a następnie dodanie cyfry.
Kod zaczyna się od małej pętli 2x2 zgodnej z ruchem wskazówek zegara, która odczytuje wszystkie wejściowe moduły 8:
_ Push a 0.
8 Turn into 8.
% Modulo. The last three commands do nothing on the first iteration
and will take the last character code modulo 8 on further iterations.
, Read a character from STDIN or -1 at EOF. At EOF we will leave loop.
Teraz ;
odrzuca -1
. Wchodzimy w kolejną pętlę zgodnie z ruchem wskazówek zegara, która przesuwa górę głównego stosu (tj. Ostatniego znaku) na dół:
" No-op, does nothing.
} Move top of the stack over to aux. If it was at the bottom of the stack
this will expose a zero underneath and we leave the loop.
= Swap top of main with top of aux. The effect of the last two commands
together is to move the second-to-top stack element from main to aux.
" No-op.
Teraz jest krótki bit liniowy:
{{ Pull two characters from aux to main, i.e. the first and last (remaining)
characters of the input (mod 8).
+ Add them.
_5 Push 5.
% Modulo.
Adres IP znajduje się teraz na skrzyżowaniu, które działa jak gałąź do testowania podzielności przez 5. Jeśli wynik modulo jest niezerowy, wiemy, że dane wejściowe nie są palindromem Watsona-Cricka i skręcamy na wschód:
_ Push 0.
! Print it. The IP hits a dead end and turns around.
_ Push 0.
% Try to take modulo, but division by zero fails and the program terminates.
W przeciwnym razie musimy nadal sprawdzać resztę danych wejściowych, aby IP kontynuowało podróż na południe. Do {
ciągnie po dnie pozostałego wejścia. Jeśli wyczerpaliśmy wejście, to będzie to 0
(od dołu Aux ), a IP kontynuuje przemieszczanie się na południe:
) Increment 0 to 1.
! Print it. The IP hits a dead end and turns around.
) Increment 0 to 1.
{ Pull a zero over from aux, IP keeps moving north.
% Try to take modulo, but division by zero fails and the program terminates.
W przeciwnym razie w ciągu będzie więcej znaków do sprawdzenia. IP skręca na zachód i przechodzi do następnej (zgodnej z ruchem wskazówek zegara) pętli 2x2, która składa się głównie z no-ops:
" No-op.
" No-op.
{ Pull one value over from aux. If it's the bottom of aux, this will be
zero and the IP will leave the loop eastward.
" No-op.
Po tej pętli mamy ponownie dane wejściowe na głównym stosie, z wyjątkiem pierwszego i ostatniego znaku i zera na górze. W ;
odrzuca 0
, a następnie =
zamienia czubki stosów, ale to jest po prostu anulować pierwszy =
w pętli, ponieważ jesteśmy teraz wejściem do pętli w innym miejscu. Wypłukać i powtórzyć.