Cubix, 238 234 217 151 110 100 bytes
Economizou 14 bytes graças ao ETHProductions
u'^.:s+.;;;\-?W?rsos\(rrOIO:ur>'=o;^u.;;.>$.vUo^'rsu1;;@!\q?s*su;;IOu*+qU../;(*\(s.;<..r:''uq....qu\
Expandido:
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 \ . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Experimente online!
Experimente aqui
Explicação
O código consiste em 8 etapas, com dois loops. Vou revisar o código parte por parte.
Etapa 1 (A ^ B)
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
I O : u . . . . . . . . . . . . . . . .
U o ^ ' . . . . . . . . . . . . . . . .
; I O u . . . . . . / ; ( * \ . . . . .
? ? r : . . . . . . ? . . . \ ? ? ? ? ?
. . . . ? . . . . . ? . . . . . . . . .
? ? ? ? ?
. . . . .
. . . . .
. . . . .
. . . . .
Este é o cubo com as partes que são irrelevantes para a primeira etapa removida. O ponto de interrogação mostra as no-ops que o IP visitará, para tornar seu caminho mais claro.
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)
Agora, a pilha fica assim: A, B, A, B
Etapa 2 (preparar para o loop de impressão)
O ciclo de impressão leva 3 argumentos (os 3 principais elementos na pilha): P
, Q
e R
. P
é a quantidade de repetições, Q
é o separador (código de caractere) e R
é o número a repetir. Felizmente, o loop também cuida da exigência de que a sequência resultante termine R
, não Q
.
Queremos repetir A*
exatamente os B
tempos, então o separador é *
. Observe que a pilha começa como A, B, A, B
. Mais uma vez, removi todas as instruções irrelevantes. O IP começa no sentido S
norte.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . r . . . . . . . . . . . . . . .
. . . . r . . . . . . . . . . . . . . .
. . . . * . . . . . . . . . . . . . . .
. . . . ' . . . . . . . . . . . . . . .
. . . . S . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
'*rr # Explanation
'* # Push * (Stack: A, B, A, B, *)
rr # Rotate top three elements twice
A pilha está agora A, B, B, *, A
.
Etapa 3/6/8 (o loop de impressão)
Conceito
E . . . . .
? r s o s u
\ ( r r O <
. . . . . S
O IP entra no loop S
, apontando para o norte, e sai do loop em E
, apontando para o norte novamente. Para esta explicação, a pilha está definida como [..., A, B, C]
. As seguintes instruções são executadas. Observe que o IP não pode deixar o loop antes do ponto de interrogação; portanto, as quatro primeiras instruções sempre serão executadas.
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 ...
Implementação
Aqui está o cubo novamente, com as partes irrelevantes removidas. O IP começa em S
, apontando para o leste.
. . . . .
. . . . .
. . . . .
? r s o s
\ ( r r O
. . . . . S ' = o ; ^ u . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Como você pode ver, o IP encontra quatro instruções antes de entrar no loop. Como o código do caractere é removido novamente, alcançamos o loop exatamente com a mesma pilha em que entramos nesta parte.
'=o; # Explanation
'= # Push =
o # Output
; # Pop from stack
Dentro do loop, a explicação acima é válida.
Etapa 4 (diferenciando os IPs)
Como usamos o loop acima várias vezes e todos eles fazem com que o IP termine no mesmo local, precisamos diferenciar entre várias execuções. Primeiro, podemos distinguir entre o separador (a primeira execução tem a *
, enquanto as duas e três têm uma+
como separador). Podemos diferenciar entre as execuções 2 e 3 verificando o valor do número que é repetido. Se for esse o caso, o programa deve terminar.
Primeira comparação
Aqui está o que parece no cubo. O IP começa em S e aponta para o norte. A pilha contém [..., * or +, A or 1, 0]
. O número 1 mostra onde o IP terminará se este for o primeiro loop (apontando para o norte) e o número 2 mostra onde o IP terminará se esse for o segundo (ou terceiro) loop (apontando para o leste).
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.
Se o IP agora estiver em 1
, a pilha estará [A, *, +, -1]
. Caso contrário, a pilha é[A or 1, +, +, 0]
. Como você pode ver, ainda há um desconhecido na pilha do segundo caso, então temos que fazer outra comparação.
Segunda comparação
Porque o IP passou por etapa 5, os olhares pilha como este: [A^(B-1) or nothing, A or 1, +, +, 0]
. Se o primeiro elemento for nothing
, o segundo elemento será 1
e o inverso também será válido. O cubo fica assim, com o IP começando em S e apontando para leste. Se esse for o segundo loop, o IP terminará emE
, apontando para oeste. Caso contrário, o programa acessa @
e termina.
. . . . .
. . . . ;
. . . S W
. . . . .
. . . . .
. . . . . . . . . . . . . ; . . . . . .
. . . . . . . . . E @ ! \ q . . . . . .
. . . . . . . . . . . . ( * . . . . . .
. . . . . . . . . . . . q u . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
As instruções executadas que não fazem nada no fluxo de controle estão listadas abaixo.
;;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 pilha está agora [A^B, +, A^(B-1), A-1]
, desde que o programa não tenha terminado.
Etapa 5 (preparando para "A +" (repita A ^ (B-1)))
Infelizmente, o Cubix não tem um operador de energia, então precisamos de outro loop. No entanto, precisamos limpar a pilha primeiro, que agora contém[B, A, *, +, -1]
.
Limpando
Aqui está o cubo novamente. Como de costume, o IP começa em S (apontando para o norte) e termina em E, apontando para o oeste.
. . . ? .
. . . ; .
. . . S .
. . . . .
. . . . .
. . . . . . . . . . . . . . . . > $ . v
. . . . . . . . . . . . . . . . . . . ;
. . . . . . . . . . . . . . . . . . E <
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
;; # Explanation
;; # Remove top 2 elements (Stack: [B, A, *])
Cálculo de A ^ (B-1)
Outro loop que funciona aproximadamente o mesmo que o loop de impressão, mas é um pouco mais compacto. O IP começa em S
, apontando para o oeste, com a pilha [B, A, *]
. O IP sai E
apontando para o norte.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . . . . . . E . . . . .
. . . . . . . . . . . . . . ? s * s u .
. . . . . . . . . . . . . . \ ( s . ; S
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
O corpo do loop é o seguinte.
;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 pilha resultante é [A, A^(B-1), 0]
.
Limpando a pilha (novamente)
Agora precisamos voltar ao loop de impressão novamente, com a parte superior da pilha [..., A^(B-1), +, A]
. Para fazer isso, executamos o seguinte. Aqui está o cubo novamente,
. . ^ ? :
. . . . .
. . . . .
. . . . .
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])
Etapa 7 (preparando para o último loop)
A pilha está agora [A^B, +, A^(B-1), A-1]
, o IP começa em S
, indo para o oeste, e termina em E
, indo para a direita.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . E . . . . . . . . . . . . . .
. . . . . . u 1 ; ; S . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
As instruções executadas:
;;1 # Explanation
;; # Delete top two elements
1 # Push 1
A pilha agora parece [A^B, +, 1]
e o IP está prestes a entrar no loop de impressão, então terminamos.