Hexagony , 920 722 271 bytes
Seis tipos diferentes de loops de frutas, você diz? Foi para isso que a Hexagony foi criada .
){r''o{{y\p''b{{g''<.{</"&~"&~"&<_.>/{.\.....~..&.>}<.._...=.>\<=..}.|>'%<}|\.._\..>....\.}.><.|\{{*<.>,<.>/.\}/.>...\'/../==.|....|./".<_>){{<\....._>\'=.|.....>{>)<._\....<..\..=.._/}\~><.|.....>e''\.<.}\{{\|./<../e;*\.@=_.~><.>{}<><;.(~.__..>\._..>'"n{{<>{<...="<.>../
Ok, não foi. Oh Deus, o que eu fiz comigo mesma ...
Este código é agora um hexágono de comprimento lateral 10 (começou em 19). Provavelmente poderia ser jogado mais, talvez até no tamanho 9, mas acho que meu trabalho foi feito aqui ... Para referência, existem 175 comandos reais na fonte, muitos dos quais são espelhos potencialmente desnecessários (ou foram adicionados para cancelar um comando a partir de um caminho de cruzamento).
Apesar da aparente linearidade, o código é realmente bidimensional: o Hexagony o reorganiza em um hexágono regular (que também é um código válido, mas todo o espaço em branco é opcional no Hexagony). Aqui está o código desdobrado em todas as suas ... bem, eu não quero dizer "beleza":
) { r ' ' o { { y \
p ' ' b { { g ' ' < .
{ < / " & ~ " & ~ " & <
_ . > / { . \ . . . . . ~
. . & . > } < . . _ . . . =
. > \ < = . . } . | > ' % < }
| \ . . _ \ . . > . . . . \ . }
. > < . | \ { { * < . > , < . > /
. \ } / . > . . . \ ' / . . / = = .
| . . . . | . / " . < _ > ) { { < \ .
. . . . _ > \ ' = . | . . . . . > {
> ) < . _ \ . . . . < . . \ . . =
. . _ / } \ ~ > < . | . . . . .
> e ' ' \ . < . } \ { { \ | .
/ < . . / e ; * \ . @ = _ .
~ > < . > { } < > < ; . (
~ . _ _ . . > \ . _ . .
> ' " n { { < > { < .
. . = " < . > . . /
Explicação
Eu nem tentarei explicar todos os caminhos complicados de execução nesta versão golfada, mas o algoritmo e o fluxo de controle geral são idênticos a essa versão não-golfada, que pode ser mais fácil de estudar para os realmente curiosos depois de explicar o algoritmo:
) { r ' ' o { { \ / ' ' p { . . .
. . . . . . . . y . b . . . . . . .
. . . . . . . . ' . . { . . . . . . .
. . . . . . . . \ ' g { / . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . > . . . . < . . . . . . . . .
. . . . . . . . . . . . . . > . . ) < . . . . .
. . . . . . . . . . / = { { < . . . . ( . . . . .
. . . . . . . . . . . ; . . . > . . . . . . . . . <
. . . . . . . . . . . . > < . / e ; * \ . . . . . . .
. . . . . . . . . . . . @ . } . > { } < . . | . . . . .
. . . . . / } \ . . . . . . . > < . . . > { < . . . . . .
. . . . . . > < . . . . . . . . . . . . . . . | . . . . . .
. . . . . . . . _ . . > . . \ \ " ' / . . . . . . . . . . . .
. . . . . . \ { { \ . . . > < . . > . . . . \ . . . . . . . . .
. < . . . . . . . * . . . { . > { } n = { { < . . . / { . \ . . |
. > { { ) < . . ' . . . { . \ ' < . . . . . _ . . . > } < . . .
| . . . . > , < . . . e . . . . . . . . . . . . . = . . } . .
. . . . . . . > ' % < . . . . . . . . . . . . . & . . . | .
. . . . _ . . } . . > } } = ~ & " ~ & " ~ & " < . . . . .
. . . \ . . < . . . . . . . . . . . . . . . . } . . . .
. \ . . . . . . . . . . . . . . . . . . . . . . . < .
. . . . | . . . . . . . . . . . . . . . . . . = . .
. . . . . . \ . . . . . . . . . . . . . . . . / .
. . . . . . > . . . . . . . . . . . . . . . . <
. . . . . . . . . . . . . . . . . . . . . . .
_ . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
Honestamente, no primeiro parágrafo eu estava apenas brincando. O fato de estarmos lidando com um ciclo de seis elementos foi realmente uma grande ajuda. O modelo de memória do Hexagony é uma grade hexagonal infinita, em que cada extremidade da grade contém um número inteiro de precisão arbitrária assinado, inicializado como zero.
Aqui está um diagrama do layout da memória que usei neste programa:
O bit longo e reto à esquerda é usado como uma sequência terminada em 0, a
de tamanho arbitrário, associada à letra r . As linhas tracejadas nas outras letras representam o mesmo tipo de estrutura, cada uma girada em 60 graus. Inicialmente, o ponteiro da memória aponta para a extremidade rotulada como 1 , voltada para o norte.
O primeiro bit linear do código define a "estrela" interna das arestas com as letras roygbp
, além de definir a aresta inicial como 1
, de modo que saibamos onde o ciclo termina / começa (entre p
e r
):
){r''o{{y''g{{b''p{
Depois disso, voltamos ao limite identificado como 1 .
Agora, a ideia geral do algoritmo é esta:
- Para cada letra do ciclo, continue lendo as letras de STDIN e, se forem diferentes da letra atual, acrescente-as à string associada a essa letra.
- Quando lemos a carta que estamos procurando, armazenamos uma
e
na borda rotulada ? , porque enquanto o ciclo não estiver completo, devemos assumir que teremos que comer esse personagem também. Depois, passaremos ao redor do ringue para o próximo personagem do ciclo.
- Há duas maneiras de interromper esse processo:
- Ou nós completamos o ciclo. Nesse caso, fazemos outra rápida ronda no ciclo, substituindo todos os
e
s no ? arestas com n
s, porque agora queremos que esse ciclo permaneça no colar. Em seguida, passamos à impressão de código.
- Ou atingimos EOF (que reconhecemos como um código de caractere negativo). Nesse caso, escrevemos um valor negativo em ? borda do caractere atual (para que possamos distingui-lo facilmente de ambos
e
e n
). Em seguida, procuramos a aresta 1 (para pular o restante de um ciclo potencialmente incompleto) antes de passar para a impressão de código também.
- O código de impressão passa pelo ciclo novamente: para cada caractere no ciclo, ele limpa a sequência armazenada enquanto imprime um
e
para cada caractere. Então ele se move para o ? borda associada ao personagem. Se for negativo, simplesmente encerramos o programa. Se for positivo, basta imprimi-lo e passar para o próximo caractere. Depois de concluir o ciclo, voltamos à etapa 2.
Outra coisa que pode ser interessante é como eu implementei as seqüências de tamanho arbitrário (porque é a primeira vez que usei memória ilimitada no Hexagony).
Imagine que estamos em algum momento em que ainda estamos lendo caracteres para r (para que possamos usar o diagrama como está) e um [0] e um 1 já foram preenchidos com caracteres (tudo a noroeste deles ainda é zero) ) Por exemplo, talvez tenhamos acabado de ler os dois primeiros caracteres og
da entrada nessas bordas e agora estamos lendo a y
.
O novo personagem é lido na borda de entrada. Nós usamos o ? borda para verificar se esse caractere é igual a r
. (Há um truque bacana aqui: a hexagonia só pode distinguir entre positivo e não positivo facilmente, portanto, verificar a igualdade por subtração é irritante e requer pelo menos dois ramos. podemos comparar os valores usando o módulo, que só dará zero se forem iguais.)
Uma vez que y
é diferente de r
, passamos a borda (não marcado) para a esquerda do em e copiar o y
ali. Agora, avançamos mais pelo hexágono, copiando o caractere uma aresta cada vez mais, até que tenhamos y
a aresta oposta a pol . Mas agora já existe um caractere em um [0] que não queremos sobrescrever. Em vez disso, "arrastar" o y
em torno da próxima hexágono e verificar a 1 . Mas há um personagem lá também, então vamos mais um hexágono. Agora um [2] ainda é zero, então copiamos oy
afim disso. O ponteiro da memória agora se move de volta ao longo da corda em direção ao anel interno. Sabemos quando chegamos ao início da string, porque as bordas (não identificadas) entre a a [i] são zero enquanto ? é positivo
Essa provavelmente será uma técnica útil para escrever código não trivial no Hexagony em geral.