Esagonia , 920 722 271 byte
Sei diversi tipi di anelli di frutta, dici? Questo è ciò per cui Hexagony è stato creato .
){r''o{{y\p''b{{g''<.{</"&~"&~"&<_.>/{.\.....~..&.>}<.._...=.>\<=..}.|>'%<}|\.._\..>....\.}.><.|\{{*<.>,<.>/.\}/.>...\'/../==.|....|./".<_>){{<\....._>\'=.|.....>{>)<._\....<..\..=.._/}\~><.|.....>e''\.<.}\{{\|./<../e;*\.@=_.~><.>{}<><;.(~.__..>\._..>'"n{{<>{<...="<.>../
Ok, non lo era. Oddio, cosa ho fatto a me stesso ...
Questo codice ora è un esagono di lunghezza laterale 10 (iniziato a 19). Probabilmente potrebbe essere golfato ancora un po ', forse anche alla taglia 9, ma penso che il mio lavoro sia svolto qui ... Per riferimento, ci sono 175 comandi effettivi nella fonte, molti dei quali sono mirror potenzialmente inutili (o sono stati aggiunti per annullare fuori un comando da un percorso di attraversamento).
Nonostante l'apparente linearità, il codice è in realtà bidimensionale: Hexagony lo riorganizzerà in un esagono regolare (che è anche un codice valido, ma tutto lo spazio bianco è facoltativo in Hexagony). Ecco il codice spiegato in tutte le sue ... beh, non voglio dire "bellezza":
) { r ' ' o { { y \
p ' ' b { { g ' ' < .
{ < / " & ~ " & ~ " & <
_ . > / { . \ . . . . . ~
. . & . > } < . . _ . . . =
. > \ < = . . } . | > ' % < }
| \ . . _ \ . . > . . . . \ . }
. > < . | \ { { * < . > , < . > /
. \ } / . > . . . \ ' / . . / = = .
| . . . . | . / " . < _ > ) { { < \ .
. . . . _ > \ ' = . | . . . . . > {
> ) < . _ \ . . . . < . . \ . . =
. . _ / } \ ~ > < . | . . . . .
> e ' ' \ . < . } \ { { \ | .
/ < . . / e ; * \ . @ = _ .
~ > < . > { } < > < ; . (
~ . _ _ . . > \ . _ . .
> ' " n { { < > { < .
. . = " < . > . . /
Spiegazione
Non proverò nemmeno a iniziare a spiegare tutti i percorsi di esecuzione contorti in questa versione golfata, ma l'algoritmo e il flusso di controllo complessivo sono identici a questa versione non golfata che potrebbe essere più facile da studiare per i davvero curiosi dopo aver spiegato l'algoritmo:
) { r ' ' o { { \ / ' ' p { . . .
. . . . . . . . y . b . . . . . . .
. . . . . . . . ' . . { . . . . . . .
. . . . . . . . \ ' g { / . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . > . . . . < . . . . . . . . .
. . . . . . . . . . . . . . > . . ) < . . . . .
. . . . . . . . . . / = { { < . . . . ( . . . . .
. . . . . . . . . . . ; . . . > . . . . . . . . . <
. . . . . . . . . . . . > < . / e ; * \ . . . . . . .
. . . . . . . . . . . . @ . } . > { } < . . | . . . . .
. . . . . / } \ . . . . . . . > < . . . > { < . . . . . .
. . . . . . > < . . . . . . . . . . . . . . . | . . . . . .
. . . . . . . . _ . . > . . \ \ " ' / . . . . . . . . . . . .
. . . . . . \ { { \ . . . > < . . > . . . . \ . . . . . . . . .
. < . . . . . . . * . . . { . > { } n = { { < . . . / { . \ . . |
. > { { ) < . . ' . . . { . \ ' < . . . . . _ . . . > } < . . .
| . . . . > , < . . . e . . . . . . . . . . . . . = . . } . .
. . . . . . . > ' % < . . . . . . . . . . . . . & . . . | .
. . . . _ . . } . . > } } = ~ & " ~ & " ~ & " < . . . . .
. . . \ . . < . . . . . . . . . . . . . . . . } . . . .
. \ . . . . . . . . . . . . . . . . . . . . . . . < .
. . . . | . . . . . . . . . . . . . . . . . . = . .
. . . . . . \ . . . . . . . . . . . . . . . . / .
. . . . . . > . . . . . . . . . . . . . . . . <
. . . . . . . . . . . . . . . . . . . . . . .
_ . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
Onestamente, nel primo paragrafo stavo solo scherzando a metà. Il fatto che abbiamo a che fare con un ciclo di sei elementi è stato di grande aiuto. Il modello di memoria di Hexagony è una griglia esagonale infinita in cui ogni bordo della griglia contiene un intero con segno di precisione arbitraria, inizializzato su zero.
Ecco un diagramma del layout della memoria che ho usato in questo programma:
Il bit lungo rettilineo a sinistra viene utilizzato come stringa con terminazione 0 a
di dimensione arbitraria associata alla lettera r . Le linee tratteggiate sulle altre lettere rappresentano lo stesso tipo di struttura, ognuna ruotata di 60 gradi. Inizialmente, il puntatore della memoria punta sul bordo etichettato 1 , rivolto a nord.
Il primo bit lineare del codice imposta la "stella" interna dei bordi sulle lettere roygbp
e imposta il bordo iniziale su 1
, in modo tale che sappiamo dove finisce / inizia il ciclo (tra p
e r
):
){r''o{{y''g{{b''p{
Dopo questo, siamo di nuovo sul bordo con l'etichetta 1 .
Ora l'idea generale dell'algoritmo è questa:
- Per ogni lettera nel ciclo, continua a leggere le lettere da STDIN e, se sono diverse dalla lettera corrente, aggiungile alla stringa associata a quella lettera.
- Quando leggiamo la lettera che stiamo attualmente cercando, ne memorizziamo una
e
sul bordo con l'etichetta ? , perché finché il ciclo non è completo, dobbiamo presumere che dovremo mangiare anche questo personaggio. Successivamente, ci sposteremo sul ring per il personaggio successivo nel ciclo.
- Esistono due modi in cui questo processo può essere interrotto:
- O abbiamo completato il ciclo. In questo caso, facciamo un altro giro veloce attraverso il ciclo, sostituendo tutte quelle
e
s nel ? bordi con n
s, perché ora vogliamo che quel ciclo rimanga sulla collana. Quindi passiamo al codice di stampa.
- Oppure colpiamo EOF (che riconosciamo come un codice carattere negativo). In questo caso, scriviamo un valore negativo nel ? bordo del personaggio attuale (in modo che possiamo facilmente distinguerlo da entrambi
e
e n
). Quindi cerchiamo il bordo 1 (per saltare il resto di un ciclo potenzialmente incompleto) prima di passare anche al codice di stampa.
- Il codice di stampa attraversa nuovamente il ciclo: per ogni carattere del ciclo cancella la stringa memorizzata mentre stampa un
e
per ogni carattere. Quindi passa al ? bordo associato al personaggio. Se è negativo, terminiamo semplicemente il programma. Se è positivo, lo stampiamo semplicemente e passiamo al personaggio successivo. Una volta completato il ciclo torniamo al passaggio 2.
Un'altra cosa che potrebbe essere interessante è il modo in cui ho implementato stringhe di dimensioni arbitrarie (perché è la prima volta che utilizzo la memoria illimitata in Hexagony).
Immagina di essere a un certo punto in cui stiamo ancora leggendo i caratteri per r (quindi possiamo usare il diagramma così com'è) e uno [0] e un 1 sono già stati riempiti di caratteri (tutto a nord-ovest di loro è ancora zero ). Ad esempio, forse abbiamo appena letto i primi due caratteri og
dell'input in quei bordi e ora stiamo leggendo a y
.
Il nuovo personaggio viene letto nel bordo interno. Usiamo il ? bordo per verificare se questo personaggio è uguale a r
. (C'è un trucco ingegnoso qui: l'esagonia può facilmente distinguere tra positivo e non positivo, quindi controllare l'uguaglianza tramite sottrazione è fastidioso e richiede almeno due rami. Ma tutte le lettere sono meno di un fattore 2 l'una dall'altra, quindi possiamo confrontare i valori prendendo il modulo, che darà zero solo se sono uguali.)
Perché y
è diverso da r
, spostiamo il bordo (senza etichetta) a sinistra di in e copiamo y
lì. Ora ci spostiamo ulteriormente intorno all'esagono, copiando il personaggio un bordo ogni volta ulteriormente, fino a quando non abbiamo y
il bordo sul lato opposto di dentro . Ma ora c'è già un personaggio in uno [0] che non vogliamo sovrascrivere. Invece, "trasciniamo" y
attorno all'esagono successivo e controlliamo un 1 . Ma c'è anche un personaggio lì, quindi andiamo più avanti un altro esagono. Ora un [2] è ancora zero, quindi copiamo il filey
dentro. Il puntatore della memoria ora si sposta indietro lungo la corda verso l'anello interno. Sappiamo quando abbiamo raggiunto l'inizio della stringa, perché i bordi (senza etichetta) tra a [i] sono tutti zero mentre ? è positivo.
Questa sarà probabilmente una tecnica utile per scrivere codice non banale in Hexagony in generale.