<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
L'input è Nseguito dalla stringa, separata da qualsiasi carattere non numerico.
Provalo online!
Questo è stato scritto in collaborazione con Sp3000 (il che significa che non potrei essere disturbato a capire un algoritmo, quindi ha iniziato a lavorarci su, ha trovato una soluzione da 118 byte ma non poteva essere disturbato a giocare a golf, quindi ho fatto il golf. .. yay per il lavoro di squadra).
Spiegazione
Primer normale di Sp (come al solito leggermente modificato):
- Labyrinth è un linguaggio 2D basato su stack con due stack, principale e ausiliario. Praticamente tutto accade nello stack principale, ma puoi spostare i valori sull'altro, ad esempio per invertirli o salvarli per dopo.
- Le pile sono senza fondo e piene di zeri, quindi spuntare da una pila vuota non è un errore.
- L'esecuzione inizia dal primo carattere valido (qui in alto a sinistra). Ad ogni giunzione, dove ci sono due o più possibili percorsi che il puntatore dell'istruzione (IP) deve prendere, la parte superiore dello stack viene controllata per determinare dove andare dopo. Il negativo è girare a sinistra, zero è andare avanti e il positivo è girare a destra. Sebbene ciò intendesse rendere il codice simile a passaggi tortuosi e tortuosi, non c'è nulla che ti impedisca di creare "stanze" in cui queste condizioni sono controllate in ogni cella. Questi possono produrre comportamenti abbastanza imprevedibili, ma sono ottimi per il golf.
- Il codice sorgente (e quindi il layout del labirinto) può essere modificato in fase di esecuzione utilizzando il
<>^vquale sposta ciclicamente una riga o colonna o la griglia.
" sono vietati.
Eccoci qui.
Il codice inizia sul <, che è un trucco da golf che ho usato alcune volte quando ho iniziato con un lungo pezzo di codice lineare. Sposta ciclicamente la prima riga a sinistra, con l'IP su di essa , quindi l'origine appare così:
<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
Ma ora l'IP non può spostarsi da nessuna parte, quindi esegue <nuovamente. Questo continua fino a quando non raggiungiamo questo stato:
<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
A questo punto, l'IP può lasciare la cella e iniziare a eseguire la seconda riga a partire da ?. Quindi ecco il codice lineare suddiviso:
? # Read the first integer on STDIN, i.e. N.
:} # Duplicate it and move one copy over to the auxiliary stack.
, # Read the separator character.
,. # Read the first character of the input string and directly print it.
L'IP ora entra in questa stanza 3x2, che in realtà è due anelli 2x2 strettamente compressi (sovrapposti) in senso orario. Il primo ciclo legge e scarta i N-1caratteri da STDIN.
; # Discard the top of the stack. On the first iteration, this is the
# separator we've already read. On subsequent iterations this will be
# one of the N-1 characters from the input string.
( # Decrement N. If this hits zero, we leave the loop, otherwise we continue.
, # Read the next character from STDIN to be discarded.
Ora entriamo nel secondo ciclo che legge il resto della stringa di input. Siamo in grado di rilevare EOF perché ,tornerà -1in quel caso, facendo girare l'IP a sinistra.
, # Read a character. Exit the loop if EOF.
( # Decrement it.
Tale decremento non è effettivamente utile, ma possiamo annullarlo in un secondo momento gratuitamente e qui ci consente di sovrapporre i due loop.
Se prendiamo l' 5 ABCDEFGHIJKLMNOPinput come esempio, lo stack si presenta così:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' -1 | 5 ... ] Auxiliary
Si noti che questi corrispondono effettivamente ai caratteri di input FGHIJKLMNOP(perché li abbiamo decrementati) e che in realtà non vogliamo stampare il primo di questi (abbiamo scartato solo i N-1caratteri, ma vogliamo saltare N).
Ora c'è un breve bit lineare che prepara lo stack per il ciclo successivo:
; # Discard the -1.
= # Swap the tops of the stacks, i.e. N with the last character.
# By putting the last character on the auxiliary stack, we ensure that
# it doesn't get discarded in the next loop.
} # Move N over to the auxiliary stack as well.
Le pile ora sembrano:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' | 5 'O' ... ] Auxiliary
Entriamo in un altro loop 2x2 in senso orario. Questo scarta i migliori Npersonaggi dallo stack principale:
; # Discard the top of the main stack.
{ # Pull N over from the auxiliary stack.
( # Decrement it. It it's 0 we leave the loop.
} # Push N back to the auxiliary stack.
Quando usciamo dal loop si =scambia di nuovo quello 0e l'ultimo carattere della stringa di input. Ora le pile sembrano così:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'O' | ... ] Auxiliary
Vogliamo stampare il contenuto dello stack principale (tranne l'elemento inferiore e tutti incrementati di 1), da sinistra . Ciò significa che dobbiamo trasferirlo nello stack ausiliario. Ecco cosa fa il prossimo ciclo 2x2 (in senso orario):
{ # Pull an element over from the auxiliary stack. This is necessary so we
# have a 0 on top of the stack when entering the loop, to prevent the IP
# from turning right immediately.
} # Move the top of the main stack back to the auxiliary stack. If this was the
# bottom of the stack, exit the loop.
) # Increment the current character.
} # Move it over to the auxiliary stack.
Stack ora:
Main [ ... | 'F' 'G' 'H' 'I' 'J' 'P] ... ] Auxiliary
Spostiamo il primo di quelli (quello che non vogliamo stampare) nella pila principale con {. E ora entriamo nell'ultimo ciclo 2x2 (in senso antiorario ), che stampa il resto:
{ # Pull another character over from the auxiliary stack. Exit the loop
# if that's the zero at the bottom of the stack.
. # Print the character.
Finalmente terminiamo il programma con @.
'il personaggio del conteggio? Ad esempio''123321:?