:?
:
#/)
\ #
!"*@
"
Pruébalo en línea!
Esto genera los resultados en el orden C, B, A
separado por saltos de línea.
Explicación
Como de costumbre, una breve cartilla de laberinto:
- Labyrinth tiene dos pilas de enteros de precisión arbitraria, main y aux (iliary), que inicialmente se rellenan con una cantidad infinita (implícita) de ceros. Solo usaremos main para esta respuesta.
- El código fuente se asemeja a un laberinto, donde el puntero de instrucción (IP) sigue los corredores cuando puede (incluso en las esquinas). El código comienza en el primer carácter válido en el orden de lectura, es decir, en la esquina superior izquierda en este caso. Cuando la IP llega a cualquier forma de unión (es decir, varias celdas adyacentes además de la que proviene), elegirá una dirección basada en la parte superior de la pila principal. Las reglas básicas son: gire a la izquierda cuando sea negativo, siga adelante cuando sea cero, gire a la derecha cuando sea positivo. Y cuando uno de estos no es posible porque hay un muro, entonces la IP tomará la dirección opuesta. La IP también se da vuelta cuando llega a callejones sin salida.
A pesar de los dos no-ops ( "
) que hacen que el diseño parezca un poco derrochador, estoy bastante contento con esta solución, porque su flujo de control es bastante sutil.
La IP comienza en la esquina superior izquierda a la :
derecha. Inmediatamente llegará a un callejón sin salida ?
y se dará la vuelta, de modo que el programa realmente comience con este código lineal:
: 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.
Eso significa que ahora tenemos tres copias de n
en la pila principal, pero su profundidad es 4
. Eso es conveniente porque significa que podemos apilar la profundidad para recuperar el multiplicador actual mientras trabajamos a través de las copias de la entrada.
La IP ahora entra en un bucle 3x3 (en sentido horario). Tenga en cuenta que #
, lo que empuja la profundidad de la pila, siempre empujará un valor positivo de modo que sepamos que la IP siempre girará hacia el este en este punto.
El cuerpo del bucle es este:
# 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.
Después de recorrer el bucle (hasta !
) tres veces, todas las copias n
se agotan y se revela el cero debajo. Debido a la "
parte inferior (que de otro modo parece bastante inútil), esta posición es un cruce. Eso significa que con un cero en la parte superior de la pila, el IP intenta ir en línea recta (oeste), pero debido a que hay un muro, en realidad gira 180 grados y se mueve hacia el este como si hubiera tocado un callejón sin salida.
Como resultado, ahora se ejecuta el siguiente bit:
" 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
) si se especifica claramente en la respuesta?