2.}<@>%?<{>$"/\M!8;
Legível:
2 . }
< @ > %
? < { > $
" / \ M
! 8 ;
Experimente online!
Provavelmente isso pode ser jogado com um byte ou dois, mas isso pode exigir um layout realmente engenhoso, que pode ser encontrado com mais facilidade por força bruta (mesmo que demore um pouco para encontrá-lo).
Explicação de alto nível
O programa segue principalmente esse pseudocódigo:
while (read number is not zero)
{
if (number is even)
print number;
}
O que abusa de como o Hexagony tenta ler um número quando STDIN está vazio (retorna um zero). Muito obrigado a Martin pela ajuda na criação dessa abordagem.
Explicação completa
Ainda não brinquei com o Mono para executar o fantástico IDE esotérico de Timwi , por isso me apoiei no Martin para me fornecer algumas fotos bonitas e úteis!
Primeiro, uma pequena cartilha sobre o fluxo de controle básico no Hexagony. O primeiro ponteiro de instrução (IP), que é o único usado neste programa, começa no canto superior esquerdo do código-fonte hexagonal e começa a se mover para a direita. Sempre que o IP sai da borda do hexágono, ele se moveside_length - 1
linhas em direção ao meio do hexágono. Como este programa usa um hexágono lateral de três lados, o IP sempre moverá duas linhas quando isso acontecer. A única exceção é se sair da linha do meio, onde se moverá condicionalmente para a parte superior ou inferior do hexágono, dependendo do valor da borda da memória atual.
Agora um pouco sobre condicionais. Os únicos condicionais no Hexagony para fluxo de controle são>
, <
e a borda média do hexágono. Todos eles seguem uma regra constante: se o valor na borda da memória atual for zero ou se o fluxo de controle negativo se mover para a esquerda e se for positivo, o controle fluirá para a direita. Os colchetes maior e menor que o redirecionam o IP em ângulos de sessenta graus, enquanto a borda do hexágono controla para qual linha o IP salta.
A Hexagony também possui um modelo de memória especial, onde todos os dados são armazenados nas bordas de uma grade hexagonal infinita. Este programa usa apenas três arestas: uma para armazenar duas, uma para o número atualmente lido e uma para o módulo número dois. Parece algo como:
Mod \ / Input
|
2
Não vou explicar cuidadosamente onde estamos na memória em cada ponto durante a explicação do programa; portanto, volte aqui se você ficar confuso com o local em que estamos na memória.
Com tudo isso fora do caminho, a explicação real pode começar. Primeiro, preenchemos a borda "2" na memória com um 2, depois executamos um no-op e movemos o ponteiro da memória para a direita (2.}
).
Em seguida, começamos o loop principal do programa. Lemos o primeiro número de STDIN e, em seguida, atingimos um condicional ( ?<
). Se não houver mais números no STDIN, isso indica um zero na borda da memória atual; portanto, vire à esquerda na @
, que encerra o programa. Caso contrário, saltamos de um espelho, movemos o ponteiro de memória para trás e para a esquerda, envolvemos o hexágono para calcular o restante da divisão da entrada por 2 e, em seguida, atingimos outra condição ( /"%>
).
Se o restante for um (ou seja, o número era ímpar), viramos à direita seguindo o caminho azul acima, iniciando novamente o no-op, depois envolvemos a parte inferior do hexágono, multiplicamos a aresta atual por 10 e adicionamos oito, rebate alguns espelhos, faça a mesma multiplicação e adição novamente, colocando 188 na borda atual, voltando para o topo do hexágono, executando o no-op novamente e finalmente encerrando o programa ( .8/\8.@
). Esse resultado complicado foi um acidente feliz, eu originalmente havia escrito um pouco mais lógico da lógica, mas percebi que podia removê-lo em favor do no-op, que eu achava mais no espírito da Hexagony.
Se o restante for zero, vire à esquerda seguindo o caminho vermelho acima. Isso faz com que movamos o ponteiro da memória para a esquerda e imprima o valor lá (o valor de entrada) como um número. O espelho que encontramos age como não operacional por causa da direção que estamos seguindo ( ). Como 77 é positivo, movemos para a direita na parte inferior do hexágono e, por causa do trampolim, pulamos a primeira instrução ( ). Em seguida, multiplicamos a borda da memória atual por 10 e adicionamos 8, obtendo 778. Em seguida, emitimos esse valor mod 256 (10) como um caractere ASCII, que passa a ser uma nova linha. Finalmente, saímos do hexágono e retornamos ao primeiro, que substitui o 778 pelo próximo valor de entrada.{/!
). Em seguida, atingimos a borda do hexágono, que age condicional com apenas um resultado, já que o valor de entrada de antes já foi testado como positivo, então sempre avançamos para a direita (se você se imaginar voltado para a IP) . Em seguida, multiplicamos a entrada por 10 e adicionamos duas, apenas para mudar de direção, envolver e exagerar o novo valor com o valor ASCII da letra maiúscula M, 77. Em seguida, atingimos alguns espelhos e saímos pela borda do meio da tela. o hexágono com um trampolim (2<M\>$
!
?