<#; "#: ={},>
}=}(.);("@
Eine weitere Zusammenarbeit mit @ MartinBüttner, der eigentlich am meisten getan hat fast alle der Golf für diese ein. Durch die Überarbeitung des Algorithmus ist es uns gelungen, die Programmgröße um einiges zu reduzieren!
Probieren Sie es online!
Erläuterung
Ein kurzer Labrinth-Primer:
Labyrinth ist eine stapelbasierte 2D-Sprache. Es gibt zwei Stapel, einen Haupt- und einen Hilfsstapel, und das Abspringen von einem leeren Stapel ergibt Null.
An jeder Kreuzung, an der es mehrere Pfade gibt, auf denen sich der Befehlszeiger nach unten bewegen kann, wird die Oberseite des Hauptstapels überprüft, um festzustellen, wohin er als nächstes gehen soll. Negativ ist links abbiegen, Null ist geradeaus und positiv ist rechts abbiegen.
Die zwei Stapel von Ganzzahlen mit willkürlicher Genauigkeit sind hinsichtlich der Speicheroptionen nicht sehr flexibel. Um die Zählung durchzuführen, verwendet dieses Programm die beiden Stapel tatsächlich als Band, wobei das Verschieben eines Wertes von einem Stapel zum anderen der Bewegung eines Speicherzeigers um eine Zelle nach links / rechts gleicht. Es ist jedoch nicht ganz dasselbe, da wir auf dem Weg nach oben einen Schleifenzähler mitziehen müssen.
Zunächst wird mit <
und >
an beiden Enden ein Versatz eingefügt, und die Codezeile wird um einen Versatz nach links oder rechts gedreht. Dieser Mechanismus wird verwendet, um den Code in einer Schleife laufen zu lassen - das <
Pops eine Null und dreht die aktuelle Zeile nach links, wobei die IP rechts vom Code steht, und das >
Pops eine weitere Null und repariert die Zeile zurück.
Folgendes passiert bei jeder Iteration im Zusammenhang mit dem obigen Diagramm:
[Section 1]
,} Read char of input and shift to aux - the char will be used as a counter
to determine how many elements to shift
[Section 2 - shift loop]
{ Shift counter from aux
" No-op at a junction: turn left to [Section 3] if char was EOF (-1), otherwise
turn right
( Decrement counter; go forward to [Section 4] if zero, otherwise turn right
= Swap tops of main and aux - we've pulled a value from aux and moved the
decremented counter to aux, ready for the next loop iteration
[Section 3]
@ Terminate
[Section 4]
; Pop the zeroed counter
) Increment the top of the main stack, updating the count of the number of times
we've seen the read char
: Copy the count, to determine how many chars to output
[Section 5 - output loop]
#. Output (number of elements on stack) as a char
( Decrement the count of how many chars to output; go forward to [Section 6]
if zero, otherwise turn right
" No-op
[Section 6]
} Shift the zeroed counter to aux
[Section 7a]
This section is meant to shift one element at a time from main to aux until the main
stack is empty, but the first iteration actually traverses the loop the wrong way!
Suppose the stack state is [... a b c | 0 d e ...].
= Swap tops of main and aux [... a b 0 | c d e ...]
} Move top of main to aux [... a b | 0 c d e ...]
#; Push stack depth and pop it (no-op)
= Swap tops of main and aux [... a 0 | b c d e ...]
Top is 0 at a junction - can't move
forwards so we bounce back
; Pop the top 0 [... a | b c d e ... ]
The net result is that we've shifted two chars from main to aux and popped the
extraneous zero. From here the loop is traversed anticlockwise as intended.
[Section 7b - unshift loop]
# Push stack depth; if zero, move forward to the <, else turn left
}= Move to aux and swap main and aux, thus moving the char below (stack depth)
to aux
; Pop the stack depth