Cubix, 238 234 217 151 110 100 байт
Збережено 14 байт завдяки ETHProductions
u'^.:s+.;;;\-?W?rsos\(rrOIO:ur>'=o;^u.;;.>$.vUo^'rsu1;;@!\q?s*su;;IOu*+qU../;(*\(s.;<..r:''uq....qu\
Розширено:
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 \ . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Спробуйте в Інтернеті!
Спробуйте тут
Пояснення
Код складається з 8 кроків, з двома петлями. Я перейду частину коду за частиною.
Крок 1 (A ^ B)
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
I O : u . . . . . . . . . . . . . . . .
U o ^ ' . . . . . . . . . . . . . . . .
; I O u . . . . . . / ; ( * \ . . . . .
? ? r : . . . . . . ? . . . \ ? ? ? ? ?
. . . . ? . . . . . ? . . . . . . . . .
? ? ? ? ?
. . . . .
. . . . .
. . . . .
. . . . .
Це куб з вилученими частинами, які не мають відношення до першого кроку. Знак питання показує, що IP не відвідає, щоб зробити його шлях більш зрозумілим.
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)
Тепер стек виглядає приблизно так: A, B, A, B
Крок 2 (підготовка до циклу друку)
Цикл друку приймає 3 аргументу (верхні 3 елементів на стеку): P, Qі R. P- кількість повторів, Qє роздільником (код символу) і Rє числом, яке потрібно повторити. На щастя, цикл також піклується про вимогу, щоб отримана рядок закінчувалася R, а не Q.
Ми хочемо повторити A*рівно Bрази, тому роздільник є *. Зауважте, що стек починається як A, B, A, B. Ще раз я видалив усі невідповідні інструкції. IP починається у Sнапрямку на північ.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . r . . . . . . . . . . . . . . .
. . . . r . . . . . . . . . . . . . . .
. . . . * . . . . . . . . . . . . . . .
. . . . ' . . . . . . . . . . . . . . .
. . . . S . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
'*rr # Explanation
'* # Push * (Stack: A, B, A, B, *)
rr # Rotate top three elements twice
Стек зараз A, B, B, *, A .
Крок 3/6/8 (цикл друку)
Концепція
E . . . . .
? r s o s u
\ ( r r O <
. . . . . S
IP входить у цикл через S, спрямований на північ, і виходить з циклу на E, знову вказуючи на північ. Для цього пояснення встановлюється стек [..., A, B, C]. Наступні інструкції виконуються. Зауважте, що IP не може залишити цикл перед знаком питання, тому перші чотири інструкції завжди будуть виконуватися.
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 ...
Впровадження
Ось знову куб, з невідповідними частинами вилучені. ІС починається з S, вказуючи на схід.
. . . . .
. . . . .
. . . . .
? r s o s
\ ( r r O
. . . . . S ' = o ; ^ u . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Як бачимо, до входу в цикл IP надходить чотири інструкції. Оскільки код символу знову видалено, ми дістаємося до циклу з точно таким же стеком, як і ми ввели цю частину.
'=o; # Explanation
'= # Push =
o # Output
; # Pop from stack
Всередині циклу справедливе пояснення.
Крок 4 (диференціація IP-адрес)
Оскільки ми використовуємо вищевказаний цикл кілька разів, і всі вони спричиняють, що IP-адреса закінчується в одному місці, нам доведеться розрізняти кілька прогонів. По-перше, ми можемо розрізнити роздільник (перший запуск має a *, тоді як прогони два та три мають a+ як роздільник). Ми можемо розмежувати прогони 2 і 3, перевіривши значення числа, яке повторюється. Якщо це одне, програму слід припинити.
Перше порівняння
Ось як це виглядає на кубі. IP починається з S та вказує на північ. Стек містить [..., * or +, A or 1, 0]. Число 1 показує, де закінчиться IP, якщо це перший цикл (вказує на північ), а число 2 показує, де IP закінчиться, якщо це другий (або третій) цикл (вказує на схід).
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.
Якщо IP-адреса зараз знаходиться 1, стек є [A, *, +, -1]. Інакше стек є[A or 1, +, +, 0] . Як бачите, у стеку другого випадку все ще є невідоме, тому ми маємо зробити ще одне порівняння.
Друге порівняння
Оскільки IP пройшов крок 5, стек виглядає наступним чином : [A^(B-1) or nothing, A or 1, +, +, 0]. Якщо перший елемент є nothing, другий елемент є 1, і зворотний також має місце. Куб виглядає приблизно так, IP починається з S і спрямований на схід. Якщо це другий цикл, IP закінчується на E, вказуючи на захід. В іншому випадку програма натискає @та припиняється.
. . . . .
. . . . ;
. . . S W
. . . . .
. . . . .
. . . . . . . . . . . . . ; . . . . . .
. . . . . . . . . E @ ! \ q . . . . . .
. . . . . . . . . . . . ( * . . . . . .
. . . . . . . . . . . . q u . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Нижче наведено інструкції, які нічого не роблять для потоку управління.
;;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
Стек тепер є за [A^B, +, A^(B-1), A-1]умови, що програма не завершилася.
Крок 5 (підготовка до "A +" (повтор A ^ (B-1)))
На жаль, у Cubix немає енергооператора, тому нам потрібна ще одна петля. Однак нам потрібно спочатку очистити стек, який зараз міститься[B, A, *, +, -1] .
Очищення
Ось знову куб. Як завжди, IP починається з S (вказує на північ) і закінчується на E, вказуючи на захід.
. . . ? .
. . . ; .
. . . S .
. . . . .
. . . . .
. . . . . . . . . . . . . . . . > $ . v
. . . . . . . . . . . . . . . . . . . ;
. . . . . . . . . . . . . . . . . . E <
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
;; # Explanation
;; # Remove top 2 elements (Stack: [B, A, *])
Обчислення A ^ (B-1)
Ще один цикл, який працює приблизно так само, як і цикл друку, але трохи компактніший. IP починається з S, вказуючи на захід, з стека [B, A, *]. ІС виходить у Eнапрямку на північ.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . . . . . . E . . . . .
. . . . . . . . . . . . . . ? s * s u .
. . . . . . . . . . . . . . \ ( s . ; S
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Тіло петлі таке.
;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 ...
Отриманий стек є [A, A^(B-1), 0].
Почищення стека (знову)
Тепер нам потрібно дістатись до циклу друку з верхньою частиною стека [..., A^(B-1), +, A]. Для цього ми виконуємо наступне. Ось знову куб,
. . ^ ? :
. . . . .
. . . . .
. . . . .
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])
Крок 7 (підготовка до останнього циклу)
Стек зараз є [A^B, +, A^(B-1), A-1], IP починається з S, ідучи на захід, і закінчується E, рухаючись праворуч.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . E . . . . . . . . . . . . . .
. . . . . . u 1 ; ; S . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Виконані інструкції:
;;1 # Explanation
;; # Delete top two elements
1 # Push 1
Тепер стек виглядає так [A^B, +, 1], і IP-адрес ось-ось увійде в цикл друку, тому ми закінчили.