Cubix, 238 234 217 151 110 100 bajtów
Zaoszczędzono 14 bajtów dzięki ETHProductions
u'^.:s+.;;;\-?W?rsos\(rrOIO:ur>'=o;^u.;;.>$.vUo^'rsu1;;@!\q?s*su;;IOu*+qU../;(*\(s.;<..r:''uq....qu\
Rozszerzony:
u ' ^ . :
s + . ; ;
; \ - ? W
? r s o s
\ ( r r O
I O : u r > ' = o ; ^ u . ; ; . > $ . v
U o ^ ' r s u 1 ; ; @ ! \ q ? s * s u ;
; I O u * + q U . . / ; ( * \ ( s . ; <
. . r : ' ' u q . . . . q u \ . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Wypróbuj online!
Wypróbuj tutaj
Wyjaśnienie
Kod składa się z 8 kroków z dwiema pętlami. Przejrzę kod po części.
Krok 1 (A ^ B)
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
I O : u . . . . . . . . . . . . . . . .
U o ^ ' . . . . . . . . . . . . . . . .
; I O u . . . . . . / ; ( * \ . . . . .
? ? r : . . . . . . ? . . . \ ? ? ? ? ?
. . . . ? . . . . . ? . . . . . . . . .
? ? ? ? ?
. . . . .
. . . . .
. . . . .
. . . . .
To jest sześcian z usuniętymi częściami, które nie mają znaczenia dla pierwszego kroku. Znak zapytania pokazuje brak operacji, które odwiedzi adres IP, aby jego ścieżka była bardziej przejrzysta.
IO:'^o;IO:r*(; # Explanation
I # Push the first input (A)
O # output that
: # duplicate it
'^ # Push the character "^"
o # output that
; # pop it from the stack
I # Push the second input (B)
O # output that
: # duplicate
r # rotate top 3 elements
* # Push the product of the top two elements
( # decrease it by one
; # pop it from the stack (making the last
# two operations useless, but doing it
# this way saves 10B)
Teraz stos wygląda następująco: A, B, A, B
Krok 2 (przygotuj się do wydruku w pętli)
Pętla drukowania trwa 3 argumenty (3 najlepsze elementy na stosie): P
, Q
i R
. P
oznacza liczbę powtórzeń, Q
jest separatorem (kodem znaków) i R
jest liczbą do powtórzenia. Na szczęście, pętla dba również wymogu, że otrzymany ciąg powinien zakończyć się w R
nie Q
.
Chcemy powtarzać A*
dokładnie B
tyle razy, więc separatorem jest *
. Zauważ, że stos zaczyna się jako A, B, A, B
. Po raz kolejny usunąłem wszystkie nieistotne instrukcje. Adres IP zaczyna się od S
wskazującej północy.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . r . . . . . . . . . . . . . . .
. . . . r . . . . . . . . . . . . . . .
. . . . * . . . . . . . . . . . . . . .
. . . . ' . . . . . . . . . . . . . . .
. . . . S . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
'*rr # Explanation
'* # Push * (Stack: A, B, A, B, *)
rr # Rotate top three elements twice
Stos jest teraz A, B, B, *, A
.
Krok 3/6/8 (pętla drukująca)
Pojęcie
E . . . . .
? r s o s u
\ ( r r O <
. . . . . S
IP wchodzi do pętli przez S
, wskazując na północ i wychodzi z pętli w E
, ponownie wskazując na północ. Dla tego wyjaśnienia stos jest ustawiony na [..., A, B, C]
. Wykonane są następujące instrukcje. Zauważ, że adres IP nie może opuścić pętli przed znakiem zapytania, więc pierwsze cztery instrukcje będą zawsze wykonywane.
Orr(?rsos # Explanation
O # Output `C`
rr # Rotate top three elements twice (Stack: [..., B, C, A])
( # Decrease A by one (Stack: [..., B, C, A-1])
? # If top of stack (A) > 0:
r # Rotate top of stack (Stack: [..., A-1, B, C])
s # Swap top elements (Stack: [..., A-1, C, B])
o # Output top of stack (B) as character code
s # Swap top elements (Stack: [..., A-1, B, C]
#
# ... and repeat ...
Realizacja
Oto znowu sześcian, z usuniętymi nieistotnymi częściami. Adres IP zaczyna się od S
, wskazując na wschód.
. . . . .
. . . . .
. . . . .
? r s o s
\ ( r r O
. . . . . S ' = o ; ^ u . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Jak widać, IP napotyka cztery instrukcje, zanim trafi do pętli. Ponieważ kod znakowy jest ponownie usuwany, dochodzimy do pętli z dokładnie takim samym stosem, jak weszliśmy do tej części.
'=o; # Explanation
'= # Push =
o # Output
; # Pop from stack
Wewnątrz pętli obowiązuje powyższe wyjaśnienie.
Krok 4 (różnicowanie adresów IP)
Ponieważ używamy powyższej pętli wiele razy, a wszystkie powodują, że adres IP kończy się w tym samym miejscu, musimy rozróżnić wiele przebiegów. Po pierwsze możemy rozróżnić separator (pierwszy przebieg ma a *
, podczas gdy drugi i trzeci mają +
separator jako). Możemy rozróżnić przebiegi 2 i 3, sprawdzając wartość liczby, która się powtarza. Jeśli tak jest, program powinien zakończyć się.
Pierwsze porównanie
Oto jak to wygląda na kostce. Adres IP zaczyna się w punkcie S i wskazuje na północ. Stos zawiera [..., * or +, A or 1, 0]
. Liczba 1 pokazuje, gdzie kończy się IP, jeśli jest to pierwsza pętla (skierowana na północ), a liczba 2 pokazuje, gdzie kończy się IP, jeśli jest to druga (lub trzecia) pętla (skierowana na wschód).
u ' . . .
s + . 1 .
; \ - ? 2
S . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
;s'+-? # Explanation
; # Delete top element (0)
s # Swap the top two elements (Stack: 1/A, */+)
'+ # Push the character code of +
- # Subtract the top two elements and push
# that to the stack (Stack: 1/A, */+, +, (*/+)-+)
? # Changes the direction based on the top
# item on the stack. If it's 0 (if (*/+) == +)
# the IP continues going right, otherwise, it
# turns and continues going north.
Jeśli adres IP jest teraz 1
ustawiony, stos jest [A, *, +, -1]
. W przeciwnym razie stos jest [A or 1, +, +, 0]
. Jak widać, na stosie drugiego przypadku wciąż jest nieznany, więc musimy zrobić kolejne porównanie.
Drugie porównanie
Ponieważ IP przeszedł kroku 5, stos wygląda jak ten: [A^(B-1) or nothing, A or 1, +, +, 0]
. Jeśli pierwszym elementem jest nothing
, drugim jest 1
, i odwrotnie. Sześcian wygląda tak, z IP zaczynającym się na S i skierowanym na wschód. Jeśli jest to druga pętla, adres IP kończy się na E
, wskazując na zachód. W przeciwnym razie program uderza @
i kończy.
. . . . .
. . . . ;
. . . S W
. . . . .
. . . . .
. . . . . . . . . . . . . ; . . . . . .
. . . . . . . . . E @ ! \ q . . . . . .
. . . . . . . . . . . . ( * . . . . . .
. . . . . . . . . . . . q u . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Wykonane instrukcje, które nic nie wpływają na przepływ sterowania, są wymienione poniżej.
;;q*q(!@
;; # Delete top two elements (Stack [A^(B-1)/null, A/1, +])
q # Send top element to the bottom (Stack [+, A^(B-1)/0, A/1])
* # Push product of top two elements
# (Stack [+, A^(B-1)/0, A/1, A^B/0])
q # Send top element to the bottom
# (Stack [A^B/0, +, A^(B-1)/0, A/1])
( # Decrease the top element by 1
# (Stack [A^B/0, +, A^(B-1)/0, (A-1)/0])
! # If (top element == 0):
@ # Stop program
Stos jest teraz [A^B, +, A^(B-1), A-1]
, pod warunkiem, że program się nie zakończy.
Krok 5 (przygotowanie do „A +” (powtórz A ^ (B-1)))
Niestety Cubix nie ma operatora mocy, więc potrzebujemy kolejnej pętli. Jednak najpierw musimy wyczyścić stos, który teraz zawiera [B, A, *, +, -1]
.
Sprzątanie
Oto znowu kostka. Jak zwykle IP zaczyna się w S (wskazując na północ), a kończy w E, wskazując na zachód.
. . . ? .
. . . ; .
. . . S .
. . . . .
. . . . .
. . . . . . . . . . . . . . . . > $ . v
. . . . . . . . . . . . . . . . . . . ;
. . . . . . . . . . . . . . . . . . E <
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
;; # Explanation
;; # Remove top 2 elements (Stack: [B, A, *])
Obliczanie A ^ (B-1)
Kolejna pętla, która działa mniej więcej tak samo jak pętla drukująca, ale jest nieco bardziej kompaktowa. Adres IP zaczyna się od S
, wskazując na zachód, ze stosem [B, A, *]
. IP kończy się, E
wskazując na północ.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . . . . . . E . . . . .
. . . . . . . . . . . . . . ? s * s u .
. . . . . . . . . . . . . . \ ( s . ; S
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Ciało pętli jest następujące.
;s(?s*s # Explanation
; # Pop top element.
s # Shift top elements.
( # Decrease top element by one
? # If not 0:
s # Shift top elements again
* # Multiply
s # Shift back
#
# ... and repeat ...
Wynikowy stos to [A, A^(B-1), 0]
.
Czyszczenie stosu (ponownie)
Teraz musimy ponownie przejść do pętli drukowania, zawierając górę stosu [..., A^(B-1), +, A]
. Aby to zrobić, wykonujemy następujące czynności. Oto znowu kostka
. . ^ ? :
. . . . .
. . . . .
. . . . .
E . . . .
. . . . . s . . . . . . . . ; . . $ . .
. . . . . + q U . . . . . . S . . s . .
. . . . . ' u q . . . . . . . . . ? . .
. . . . . . . ? . . . . . . . . . ? . .
. . . . . . . ? . . . . . . . . . ? . .
. . ? . .
. . ? . .
. . ? . .
. . ? . .
. . ? . .
;:$sqq'+s # Explanation
; # Delete top element (Stack: [A, A^(B-1)])
: # Copy top element
$s # No-op
qq # Send top two elements to the bottom
# (Stack: [A^(B-1), A^(B-1), A])
'+ # Push +
# (Stack: [A^(B-1), A^(B-1), A, +])
s # Swap top two elements
# (Stack: [A^(B-1), A^(B-1), +, A])
Krok 7 (przygotowanie do ostatniej pętli)
Stos jest teraz [A^B, +, A^(B-1), A-1]
, IP zaczyna się od S
, idzie na zachód, a kończy o E
, idzie w prawo.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . E . . . . . . . . . . . . . .
. . . . . . u 1 ; ; S . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Wykonane instrukcje:
;;1 # Explanation
;; # Delete top two elements
1 # Push 1
Wygląda teraz stos [A^B, +, 1]
, a adres IP ma zamiar wejść do pętli drukowania, więc skończyliśmy.