_8
,%
;
"}{{+_5
"= %_!
= """{
;"{" )!
Termina com um erro de divisão por zero (mensagem de erro em STDERR).
Experimente online!
O layout parece realmente ineficiente, mas agora não estou vendo uma maneira de jogar golfe.
Explicação
Esta solução é baseada no truque aritmético de Dennis: pegue todos os módulos de códigos de caracteres 8
, adicione um par de ambas as extremidades e verifique se é divisível por 5
.
Primário 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.
- 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.
- Os dígitos são processados multiplicando a parte superior da pilha principal por 10 e adicionando o dígito.
O código começa com um pequeno loop 2x2 no sentido horário, que lê todos os módulos de entrada 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.
Agora ;
descarta o -1
. Entramos em outro loop no sentido horário que move o topo da pilha principal (ou seja, o último caractere) para baixo:
" 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.
Agora há um pequeno bit linear:
{{ 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.
O IP está agora em uma junção que atua como uma ramificação para testar a divisibilidade em 5. Se o resultado do módulo for diferente de zero, sabemos que a entrada não é um palíndromo de Watson-Crick e viramos para o leste:
_ 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.
Caso contrário, precisamos continuar verificando o restante da entrada, para que o IP continue indo para o sul. Ele {
puxa a parte inferior da entrada restante. Se esgotarmos a entrada, será um 0
(na parte inferior do aux ) e o IP continuará se movendo para o sul:
) 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.
Caso contrário, há mais caracteres na sequência a serem verificados. O IP vira para oeste e passa para o próximo loop 2x2 (no sentido horário), que consiste basicamente de 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.
Após esse loop, temos a entrada na pilha principal novamente, exceto seu primeiro e último caractere e com um zero no topo. Ele ;
descarta 0
e =
troca as partes superiores das pilhas, mas isso é apenas para cancelar o primeiro =
no loop, porque agora estamos inserindo o loop em um local diferente. Enxague e repita.