:?
:
#/)
\ #
!"*@
"
Experimente online!
Isso gera os resultados na ordem C, B, A
separada por alimentações de linha.
Explicação
Como de costume, uma breve cartilha de labirinto:
- O labirinto possui duas pilhas de números inteiros de precisão arbitrária, principal e auxiliar (iliária), que são inicialmente preenchidos com uma quantidade infinita (implícita) de zeros. Usaremos apenas main para esta resposta.
- O código fonte se assemelha a um labirinto, onde o ponteiro de instrução (IP) segue os corredores quando pode (mesmo nos cantos). O código começa no primeiro caractere válido em ordem de leitura, ou seja, no canto superior esquerdo neste caso. Quando o IP chega a qualquer forma de junção (ou seja, várias células adjacentes além daquela de onde veio), ele selecionará uma direção com base no topo da pilha principal. As regras básicas são: vire à esquerda quando negativo, continue em frente quando zero, vire à direita quando positivo. E quando uma dessas opções não for possível porque existe uma parede, o IP seguirá na direção oposta. O IP também muda ao atingir becos sem saída.
Apesar das duas no-ops ( "
) que fazem o layout parecer um pouco inútil, estou muito feliz com esta solução, porque seu fluxo de controle é realmente bastante sutil.
O IP começa no canto superior esquerdo à :
direita. Ele chegará imediatamente a um beco sem saída ?
e será girado, para que o programa realmente comece com esse trecho de código linear:
: 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.
Isso significa que agora temos três cópias n
na pilha principal, mas é profundo 4
. Isso é conveniente porque significa que podemos usar a profundidade da pilha para recuperar o multiplicador atual enquanto trabalhamos nas cópias da entrada.
O IP agora entra em um loop 3x3 (no sentido horário). Observe que #
, o que aumenta a profundidade da pilha, sempre gera um valor positivo, de modo que sabemos que o IP sempre girará para o leste neste momento.
O corpo do loop é 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.
Após o loop ter sido percorrido (até !
) três vezes, todas as cópias n
são usadas e o zero abaixo é revelado. Devido à parte "
inferior (que de outra forma parece bastante inútil), essa posição é uma junção. Isso significa que, com um zero no topo da pilha, o IP tenta seguir em frente (oeste), mas, como há um muro, ele faz uma curva de 180 graus e volta para o leste como se tivesse atingido um beco sem saída.
Como resultado, o seguinte bit agora é executado:
" 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
), se estiver claramente especificado na resposta?