Labyrinth , 28 25 24 23 22 byte
" >
?!?:|}\{@
@\?"":)!
È stato divertente! :) Questo è di gran lunga il programma Labyrinth più densamente compresso che ho scritto finora. Avevo così tante versioni a 20 e 21 byte che quasi funzionavano che sto ancora dubitando che sia ottimale ...
Questo prende l'input come un elenco di numeri interi positivi (con un delimitatore arbitrario) e stampa il risultato su STDOUT come numeri interi delimitati da avanzamento riga.
La caccia a 20/21 byte: ho controllato tutti i programmi del modulo
" XX
?!?X}\{@
@\?XX)!
dove X
c'è un carattere ragionevole per forza bruta, ma non ha trovato soluzioni valide. Ovviamente ciò non significa che non esiste una soluzione più breve, ma non è possibile forzare i programmi a 20 byte senza una discreta quantità di ipotesi sulla sua struttura.
Spiegazione
(La spiegazione è leggermente obsoleta, ma non sono ancora convinto che la soluzione sia ottimale, quindi aspetterò con l'aggiornamento.)
Quindi, normalmente i programmi Labyrinth dovrebbero apparire come labirinti. Mentre il puntatore dell'istruzione si trova in un corridoio, seguirà quel corridoio. Quando l'IP colpisce qualsiasi tipo di giunzione, la direzione viene determinata in base al valore massimo dello stack principale di Labyrinth (Labyrinth ha due stack, con un numero infinito di zero nella parte inferiore). Ciò significa normalmente che qualsiasi loop non banale sarà piuttosto costoso, perché se si dispone di celle non a parete in tutto il luogo tutto è una giunzione, e nella maggior parte dei casi la parte superiore dello stack non avrà il valore giusto per l'IP per prendere la strada che vorresti che prendesse. Quindi, ciò che fai è allargare i loop in modo che abbiano un intero al centro con solo un punto di entrata e uscita ben definiti ciascuno.
Ma questa volta sono stato davvero fortunato e tutto si è adattato così bene insieme, che ho potuto comprimere tutto in un grosso gruppo. :)
Il flusso di controllo inizia a _
sud. La _
spinge uno zero nello stack principale. Potrebbe sembrare una no-op, ma ciò aumenta la profondità (non implicita) dello stack di 1
cui avremo bisogno in seguito.
?
legge un numero intero da STDIN. Se non ci sono più numeri interi da leggere, questo spinge zero. In tal caso, l'IP continua a spostarsi a sud e @
termina immediatamente il programma (perché l'elenco di input è vuoto). Altrimenti, l'IP gira verso est.
Ora stiamo entrando in un circuito molto stretto con due punti di uscita:
!?;
\?
;
!
stampa il numero intero su STDOUT, lasciando solo uno zero nello stack. L'IP continua a spostarsi verso est e ?
legge il numero intero successivo. Se questo è diverso da zero, prendiamo una destra e ci spostiamo a sud. ?
ne legge un altro (il prossimo indice pari). Ancora una volta, se questo è diverso da zero, prendiamo una destra e ci spostiamo a ovest.
Quindi \
stampa un avanzamento di riga senza cambiare la pila, quindi prendiamo un altro a destra, spostandoci verso nord. !
stampa il successivo numero intero di indice pari. Poiché ora c'è almeno un intero (positivo) indice dispari nello stack, continuiamo a girare a destra e il ciclo si ripete.
Una volta che uno di questi ?
colpisce la fine dell'elenco, spingono uno zero e si spostano direttamente sul corrispondente ;
, che scarta quello zero.
Nel caso in cui ci fosse un solo elemento nell'elenco, abbiamo finito (perché l'abbiamo stampato subito), quindi l'IP continuerebbe a spostarsi verso est fino al @
, terminando di nuovo il programma (stampando un trailing avanzamento linea lungo la strada).
Altrimenti, dobbiamo stampare anche gli interi con indice dispari. In tal caso i due percorsi (dai due punti di uscita del primo anello) si fondono nel mezzo "
, girando verso est in entrambi i casi.
_
spinge uno zero per evitare di svoltare a sinistra in @
, e ;
scarta quello zero. Ora entriamo in un nuovo ciclo:
"}
""
L'IP entra nella cella in basso a sinistra, spostandosi verso nord, andando in senso orario attorno al circuito. L' }
sposta cima alla pila principale rispetto allo stack ausiliario. Mentre c'è ancora un elemento nello stack, l'IP continua a fare le sue cose. Una volta che tutto è stato spostato nello stack ausiliario (e invertito nel processo), l'IP continua invece a spostarsi verso est, entrando nell'ultimo loop:
\{@
#!
\
stampa di nuovo un avanzamento riga, {
sposta un oggetto dalla pila ausiliaria alla pagina principale. Se quello era ancora un elemento dell'elenco, sarà positivo e l'IP diventerà Sud, dove viene stampato l'elemento !
. Quindi #
spinge la profondità dello stack (e ora è qui che l'iniziale _
è importante, perché ciò #
garantisce una profondità dello stack positiva), in modo che l'IP giri ancora a destra, attraverso \
e di {
nuovo.
Dopo aver stampato tutto, {
estrae uno zero dalla parte inferiore dello stack ausiliario, l'IP continua verso est e @
termina il programma.