Cubix, 238 234 217 151 110 100 bytes
Ahorró 14 bytes gracias a 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 \ . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Pruébalo en línea!
Pruébalo aquí
Explicación
El código consta de 8 pasos, con dos bucles. Revisaré el código parte por parte.
Paso 1 (A ^ B)
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
I O : u . . . . . . . . . . . . . . . .
U o ^ ' . . . . . . . . . . . . . . . .
; I O u . . . . . . / ; ( * \ . . . . .
? ? r : . . . . . . ? . . . \ ? ? ? ? ?
. . . . ? . . . . . ? . . . . . . . . .
? ? ? ? ?
. . . . .
. . . . .
. . . . .
. . . . .
Este es el cubo con las partes que son irrelevantes para el primer paso eliminado. El signo de interrogación muestra los no-ops que visitará el IP, para dejar su camino más 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)
Ahora, la pila se ve así: A, B, A, B
Paso 2 (prepárese para el ciclo de impresión)
El bucle de impresión toma 3 argumentos (los 3 primeros elementos en la pila): P
, Q
y R
. P
es la cantidad de repeticiones, Q
es el separador (código de caracteres) y R
es el número a repetir. Por suerte, el bucle también se encarga de la exigencia de que la cadena resultante debe terminar en R
, no Q
.
Queremos repetir tiempos A*
exactos B
, entonces el separador es *
. Tenga en cuenta que la pila comienza como A, B, A, B
. Una vez más, eliminé todas las instrucciones irrelevantes. La IP comienza en el S
norte.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . r . . . . . . . . . . . . . . .
. . . . r . . . . . . . . . . . . . . .
. . . . * . . . . . . . . . . . . . . .
. . . . ' . . . . . . . . . . . . . . .
. . . . S . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
'*rr # Explanation
'* # Push * (Stack: A, B, A, B, *)
rr # Rotate top three elements twice
La pila es ahora A, B, B, *, A
.
Paso 3/6/8 (el bucle de impresión)
Concepto
E . . . . .
? r s o s u
\ ( r r O <
. . . . . S
La IP ingresa al bucle S
, apunta hacia el norte, y sale del bucle hacia E
, apuntando hacia el norte nuevamente. Para esta explicación, la pila se establece en [..., A, B, C]
. Se ejecutan las siguientes instrucciones. Tenga en cuenta que la IP no puede abandonar el bucle antes del signo de interrogación, por lo que las primeras cuatro instrucciones siempre se ejecutarán.
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 ...
Implementación
Aquí está el cubo nuevamente, con las partes irrelevantes eliminadas. La IP comienza en S
, apuntando hacia el este.
. . . . .
. . . . .
. . . . .
? r s o s
\ ( r r O
. . . . . S ' = o ; ^ u . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Como puede ver, la IP se encuentra con cuatro instrucciones antes de ingresar al bucle. Dado que el código de caracteres se elimina nuevamente, llegamos al bucle con exactamente la misma pila que ingresamos en esta parte.
'=o; # Explanation
'= # Push =
o # Output
; # Pop from stack
Dentro del bucle, la explicación anterior es válida.
Paso 4 (diferenciando las IP)
Dado que usamos el bucle anterior varias veces, y todos hacen que la IP termine en el mismo lugar, tenemos que diferenciar entre múltiples ejecuciones. Primero, podemos distinguir entre el separador (la primera ejecución tiene un *
, mientras que las ejecuciones dos y tres tienen un +
separador). Podemos diferenciar entre las ejecuciones 2 y 3 comprobando el valor del número que se repite. Si ese es uno, el programa debería finalizar.
Primera comparación
Así es como se ve en el cubo. La IP comienza en S y apunta al norte. La pila contiene [..., * or +, A or 1, 0]
. El número 1 muestra dónde terminará la IP si este es el primer bucle (apuntando hacia el norte) y el número 2 muestra dónde terminará la IP si este es el segundo (o tercer) bucle (apuntando hacia el este).
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.
Si la IP ahora está en 1
, la pila está [A, *, +, -1]
. De lo contrario, la pila es [A or 1, +, +, 0]
. Como puede ver, todavía hay una incógnita en la pila del segundo caso, por lo que tenemos que hacer otra comparación.
Segunda comparación
Debido a que la IP ha pasado por el paso 5, las miradas de pila de este tipo: [A^(B-1) or nothing, A or 1, +, +, 0]
. Si el primer elemento es nothing
, el segundo elemento es 1
, y lo contrario también se cumple. El cubo se ve así, con la IP comenzando en S y apuntando hacia el este. Si este es el segundo bucle, la IP termina en E
, apuntando hacia el oeste. De lo contrario, el programa golpea @
y finaliza.
. . . . .
. . . . ;
. . . S W
. . . . .
. . . . .
. . . . . . . . . . . . . ; . . . . . .
. . . . . . . . . E @ ! \ q . . . . . .
. . . . . . . . . . . . ( * . . . . . .
. . . . . . . . . . . . q u . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Las instrucciones ejecutadas que no hacen nada al flujo de control se enumeran a continuación.
;;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
La pila está ahora [A^B, +, A^(B-1), A-1]
, siempre que el programa no haya terminado.
Paso 5 (preparación para "A +" (repita A ^ (B-1)))
Lamentablemente, Cubix no tiene un operador de potencia, por lo que necesitamos otro bucle. Sin embargo, primero debemos limpiar la pila, que ahora contiene [B, A, *, +, -1]
.
Limpiar
Aquí está el cubo otra vez. Como de costumbre, la IP comienza en S (apuntando hacia el norte) y termina en E, apuntando hacia el oeste.
. . . ? .
. . . ; .
. . . S .
. . . . .
. . . . .
. . . . . . . . . . . . . . . . > $ . v
. . . . . . . . . . . . . . . . . . . ;
. . . . . . . . . . . . . . . . . . E <
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
;; # Explanation
;; # Remove top 2 elements (Stack: [B, A, *])
Calculando A ^ (B-1)
Otro bucle que funciona más o menos igual que el bucle de impresión, pero es un poco más compacto. La IP comienza en S
, apuntando al oeste, con pila [B, A, *]
. La IP sale E
apuntando hacia el norte.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . . . . . . E . . . . .
. . . . . . . . . . . . . . ? s * s u .
. . . . . . . . . . . . . . \ ( s . ; S
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
El cuerpo del bucle es el siguiente.
;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 ...
La pila resultante es [A, A^(B-1), 0]
.
Limpiar la pila (de nuevo)
Ahora necesitamos volver al ciclo de impresión, con la parte superior de la pila conteniendo [..., A^(B-1), +, A]
. Para hacer esto, ejecutamos lo siguiente. Aquí está el cubo otra vez,
. . ^ ? :
. . . . .
. . . . .
. . . . .
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])
Paso 7 (preparación para el último bucle)
La pila es ahora [A^B, +, A^(B-1), A-1]
, la IP comienza en S
, yendo hacia el oeste, y termina en E
, yendo hacia la derecha.
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . E . . . . . . . . . . . . . .
. . . . . . u 1 ; ; S . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Las instrucciones ejecutadas:
;;1 # Explanation
;; # Delete top two elements
1 # Push 1
La pila ahora se ve [A^B, +, 1]
y la IP está a punto de entrar en el ciclo de impresión, así que hemos terminado.