_8
,%
;
"}{{+_5
"= %_!
= """{
;"{" )!
Termina con un error de división por cero (mensaje de error en STDERR).
Pruébalo en línea!
El diseño se siente realmente ineficiente, pero no estoy viendo una forma de jugar golf en este momento.
Explicación
Esta solución se basa en el truco aritmético de Dennis: tome todos los módulos de caracteres 8
, agregue un par de ambos extremos y asegúrese de que sea divisible por 5
.
Imprimación 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.
- El código fuente se asemeja a un laberinto, donde el puntero de instrucción (IP) sigue los corredores cuando puede (incluso alrededor de 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.
- Los dígitos se procesan multiplicando la parte superior de la pila principal por 10 y luego agregando el dígito.
El código comienza con un pequeño bucle de 2x2 en sentido horario, que lee todas las entradas del módulo 8:
_ Push a 0.
8 Turn into 8.
% Modulo. The last three commands do nothing on the first iteration
and will take the last character code modulo 8 on further iterations.
, Read a character from STDIN or -1 at EOF. At EOF we will leave loop.
Ahora ;
descarta el -1
. Entramos en otro bucle en el sentido de las agujas del reloj que mueve la parte superior de la pila principal (es decir, el último carácter) hacia abajo:
" No-op, does nothing.
} Move top of the stack over to aux. If it was at the bottom of the stack
this will expose a zero underneath and we leave the loop.
= Swap top of main with top of aux. The effect of the last two commands
together is to move the second-to-top stack element from main to aux.
" No-op.
Ahora hay un bit lineal corto:
{{ Pull two characters from aux to main, i.e. the first and last (remaining)
characters of the input (mod 8).
+ Add them.
_5 Push 5.
% Modulo.
La IP está ahora en una unión que actúa como una rama para probar la divisibilidad entre 5. Si el resultado del módulo no es cero, sabemos que la entrada no es un palíndromo de Watson-Crick y giramos hacia el este:
_ Push 0.
! Print it. The IP hits a dead end and turns around.
_ Push 0.
% Try to take modulo, but division by zero fails and the program terminates.
De lo contrario, debemos seguir verificando el resto de la entrada, para que la IP siga yendo hacia el sur. El {
tira sobre la parte inferior de la entrada restante. Si hemos agotado la entrada, esta será una 0
(desde la parte inferior de aux ), y la IP continúa moviéndose hacia el sur:
) Increment 0 to 1.
! Print it. The IP hits a dead end and turns around.
) Increment 0 to 1.
{ Pull a zero over from aux, IP keeps moving north.
% Try to take modulo, but division by zero fails and the program terminates.
De lo contrario, hay más caracteres en la cadena para verificar. La IP gira hacia el oeste y pasa al siguiente ciclo 2x2 (en el sentido de las agujas del reloj) que consiste en gran medida en no-ops:
" No-op.
" No-op.
{ Pull one value over from aux. If it's the bottom of aux, this will be
zero and the IP will leave the loop eastward.
" No-op.
Después de este bucle, tenemos la entrada en la pila principal nuevamente, excepto por su primer y último carácter y con un cero en la parte superior. Los ;
descartes de la 0
y luego =
intercambia la parte superior de las pilas, pero esto es sólo para cancelar la primera =
en el circuito, porque estamos entrando ahora en el bucle en una ubicación diferente. Enjuague y repita.