:?
:
#/)
\ #
!"*@
"
Wypróbuj online!
Wyprowadza to wyniki w kolejności C, B, A
oddzielonej liniami.
Wyjaśnienie
Jak zwykle krótki podkład Labiryntowy:
- Labirynt ma dwa stosy liczb całkowitych o dowolnej precyzji, główną i pomocniczą (iliary), które są początkowo wypełnione (domyślną) nieskończoną liczbą zer. Będziemy używać main do tej odpowiedzi.
- Kod źródłowy przypomina labirynt, w którym wskaźnik instrukcji (IP) podąża 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 na podstawie górnej części 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.
Pomimo dwóch no-ops ( "
), które sprawiają, że układ wydaje się trochę marnotrawiony, jestem całkiem zadowolony z tego rozwiązania, ponieważ jego kontrola jest w rzeczywistości dość subtelna.
Adres IP zaczyna się w lewym górnym rogu po :
prawej stronie. Natychmiast uderzy w ślepy zaułek ?
i zawróci, tak że program faktycznie zacznie się od tego liniowego fragmentu kodu:
: Duplicate top of main stack. This will duplicate one of the implicit zeros
at the bottom. While this may seem like a no-op it actually increases
the stack depth to 1, because the duplicated zero is *explicit*.
? Read n and push it onto main.
: Duplicate.
: Duplicate.
Oznacza to, że mamy teraz trzy kopie n
na głównym stosie, ale jego głębokość jest 4
. Jest to wygodne, ponieważ oznacza, że możemy głębokość stosu, aby pobrać bieżący mnożnik podczas pracy z kopiami danych wejściowych.
IP wchodzi teraz w pętlę 3x3 (zgodnie z ruchem wskazówek zegara). Zauważ, że to #
, co popycha głębokość stosu, zawsze będzie wypychało wartość dodatnią, tak że wiemy, że IP w tym momencie zawsze skręci na wschód.
Ciało pętli jest następujące:
# Push the stack depth, i.e. the current multiplier k.
/ Compute n / k (rounding down).
) Increment.
# Push the stack depth again (this is still k).
* Multiply. So we've now computed (n/k+1)*k, which is the number
we're looking for. Note that this number is always positive so
we're guaranteed that the IP turns west to continue the loop.
" No-op.
! Print result. If we've still got copies of n left, the top of the
stack is positive, so the IP turns north and does another round.
Otherwise, see below...
\ Print a linefeed.
Then we enter the next loop iteration.
Po !
trzykrotnym przejściu pętli (do ) trzykrotnie, wszystkie kopie n
są zużyte i odsłania się zero poniżej. Ze względu "
na spód (który w innym przypadku wydaje się dość bezużyteczny) ta pozycja jest skrzyżowaniem. Oznacza to, że z zero na szczycie stosu, IP próbuje iść prosto (na zachód), ale ponieważ jest ściana, faktycznie wykonuje obrót o 180 stopni i przesuwa się z powrotem na wschód, jakby uderzyła w ślepy zaułek.
W rezultacie następujący bit jest teraz wykonywany:
" No-op.
* Multiply two zeros on top of the stack, i.e. also a no-op.
The top of the stack is now still zero, so the IP keeps moving east.
@ Terminate the program.
C B A
), Jeśli jest to wyraźnie określone w odpowiedzi?