<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
Auf die Eingabe Nfolgt die Zeichenfolge, die durch ein beliebiges nicht numerisches Zeichen getrennt wird.
Probieren Sie es online!
Dies wurde in Zusammenarbeit mit Sp3000 geschrieben (was bedeutet, dass ich nicht die Mühe hatte, einen Algorithmus zu finden, und er begann, daran zu arbeiten. Er kam auf eine 118-Byte-Lösung, konnte sich aber nicht die Mühe machen, sie zu spielen, also spielte ich Golf. .. yay für Teamarbeit).
Erläuterung
Sp's üblicher Primer (wie üblich leicht modifiziert):
- Labyrinth ist eine stapelbasierte 2D-Sprache mit zwei Stapeln, Main und Auxiliary. Auf dem Hauptstapel passiert so ziemlich alles, aber Sie können Werte auf den anderen Stapel verschieben, z. B. um sie umzukehren oder für später zu speichern.
- Die Stapel sind bodenlos und mit Nullen gefüllt, sodass das Herausspringen aus einem leeren Stapel kein Fehler ist.
- Die Ausführung beginnt mit dem ersten gültigen Zeichen (hier oben links). An jeder Kreuzung, an der zwei oder mehr mögliche Pfade für den Anweisungszeiger (IP) zur Verfügung stehen, wird die Oberseite des Stapels überprüft, um zu bestimmen, wohin er als Nächstes gehen soll. Negativ ist links abbiegen, Null ist vorwärts und positiv ist rechts abbiegen. Während dies bedeutete den Code aussehen wie Wickeln, kurvigen Passagen zu machen, gibt es nichts , was man aus machen „Räumen“ zu stoppen , wo diese Bedingungen in jeder Zelle überprüft werden. Diese können zu unvorhersehbarem Verhalten führen, eignen sich aber hervorragend zum Golfen.
- Der Quellcode (und damit das Layout des Labyrinths) kann zur Laufzeit geändert werden, indem
<>^vzyklisch eine Zeile oder Spalte oder das Raster verschoben wird.
" sind No-Ops.
Auf geht's.
Der Code beginnt mit dem <Golf-Trick, den ich einige Male verwendet habe, als ich mit einem langen Stück linearen Codes angefangen habe. Die erste Zeile wird zyklisch mit der IP- Adresse nach links verschoben , sodass die Quelle dann wie folgt aussieht:
<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
Aber jetzt kann sich die IP nirgendwo bewegen, also führt sie die <nochmal aus. Dies geht so lange weiter, bis wir diesen Zustand erreichen:
<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
An diesem Punkt kann die IP die Zelle verlassen und mit der Ausführung der zweiten Zeile beginnen, beginnend mit ?. Hier ist der lineare Code:
? # 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.
Die IP betritt nun diesen 3x2-Raum, der eigentlich zwei fest komprimierte (überlappende) 2 x 2-Schleifen im Uhrzeigersinn ist. Die erste Schleife liest und N-1löscht Zeichen aus 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.
Nun betreten wir die zweite Schleife, die den Rest der Eingabezeichenfolge liest. Wir können erkennen , da EOF ,zurückkehren wird -1in diesem Fall, so dass die IP links abbiegen.
, # Read a character. Exit the loop if EOF.
( # Decrement it.
Diese Dekrementierung ist eigentlich nicht sinnvoll, aber wir können sie später kostenlos rückgängig machen und hier können wir die beiden Schleifen überlappen.
Wenn wir die 5 ABCDEFGHIJKLMNOPEingabe als Beispiel nehmen, sieht der Stapel folgendermaßen aus:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' -1 | 5 ... ] Auxiliary
Beachten Sie, dass diese tatsächlich den eingegebenen Zeichen entsprechen FGHIJKLMNOP(weil wir sie dekrementiert haben) und dass wir die ersten N-1Zeichen nicht drucken möchten (wir haben nur Zeichen verworfen , möchten sie aber überspringen N).
Jetzt gibt es ein kurzes lineares Bit, das den Stack für die nächste Schleife vorbereitet:
; # 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.
Die Stapel sehen nun so aus:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' | 5 'O' ... ] Auxiliary
Wir betreten eine weitere 2 × 2-Schleife im Uhrzeigersinn. Dies verwirft die obersten NZeichen vom Hauptstapel:
; # 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.
Beim Verlassen der Schleife werden =dieses 0und das letzte Zeichen der Eingabezeichenfolge erneut ausgetauscht. Nun sehen die Stapel so aus:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'O' | ... ] Auxiliary
Wir möchten den Inhalt des Hauptstapels (mit Ausnahme des unteren Elements und alle um 1 erhöht) von links drucken . Das heißt, wir müssen es zum Hilfsstapel bringen. Das macht die nächste 2x2-Schleife (im Uhrzeigersinn):
{ # 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.
Stacks jetzt:
Main [ ... | 'F' 'G' 'H' 'I' 'J' 'P] ... ] Auxiliary
Wir verschieben die erste davon (die, die wir nicht drucken möchten) zurück in den Hauptstapel mit {. Und jetzt geben wir die letzte 2x2- Schleife ( gegen den Uhrzeigersinn ) ein, die den Rest ausgibt:
{ # 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.
Zum Schluss beenden wir das Programm mit @.
'dem Zählcharakter in unary aufzunehmen ? Zum Beispiel''123321:?