Fueue , 423 Bytes
Fueue ist ein Warteschlangen-esolang in dem das laufende Programm ist die Warteschlange.
)$$4255%%1(~):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]](H-):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
Probieren Sie es online!
Wie es funktioniert
Diese Erklärung mag aus dem Ruder gelaufen sein oder auch nicht . Andererseits weiß ich nicht, wie ich es viel kürzer erklären soll, so wie ich hoffe, dass die Leute dem folgen können.
Fueue Spickzettel
Siehe esolang Wiki - Artikel für Details, einschließlich der wenigen Funktionen , die nicht in diesem Programm verwendet.
Das Anfangsprogramm ist der Anfangszustand der Warteschlange, der die folgenden Elemente enthalten kann:
- Ganzzahlige Literale (nur nicht negative in der Quelle, aber negative können berechnet werden), die ausgeführt werden, geben ein Zeichen aus.
- Durch eckige Klammern begrenzte verschachtelte Blöcke, inert (intakt erhalten, sofern keine Funktion auf sie einwirkt).
- Funktionen, ihre Argumente sind die Elemente, die ihnen unmittelbar in der Warteschlange folgen:
+*/-%
: ganzzahlige Arithmetik ( -
ist unär, %
logische Negation). Inert, wenn keine Zahlenargumente angegeben wurden.
()<
: Element in Klammern setzen, Klammern vom Block entfernen, letztes Element zum Block hinzufügen. Die beiden letzteren sind inert, sofern kein Block folgt.
~:
: tauschen, duplizieren.
$
: copy (nimmt Nummer + Element). Inert vor Nichtzahl.
H
: Programm anhalten.
Beachten Sie, dass dies beim []
Verschachteln ()
nicht der Fall ist - letztere sind einfach separate Funktionen.
Ausführungsablaufverfolgungssyntax
Whitespace ist in Fueue optional, außer zwischen Ziffern. In den folgenden Ausführungs-Traces wird insbesondere die Programmstruktur vorgeschlagen:
- Wenn eine Funktion ausgeführt wird, werden sie und ihre Argumente durch Leerzeichen von den umgebenden Elementen abgesetzt. Wenn einige der Argumente kompliziert sind, kann auch ein Leerzeichen dazwischen stehen.
- Viele Ausführungsspuren sind links in einen "Delay-Blob" unterteilt, der von einem Teil rechts getrennt ist, der die wesentlichen Datenmanipulationen ausführt. Siehe nächster Abschnitt.
Geschweifte Klammern {}
(in Fueue nicht verwendet) werden in den Traces verwendet, um das ganzzahlige Ergebnis mathematischer Ausdrücke darzustellen. Dies schließt negative Zahlen ein, da Fueue nur nicht negative Literale hat - -
ist die Negationsfunktion.
Verschiedene metavariable Namen und ...
werden zur Bezeichnung von Werten und Abkürzungen verwendet.
Verzögerungstaktik
Intuitiv durchläuft die Ausführung die Warteschlange und ändert teilweise, was sie durchläuft. Die Ergebnisse einer Funktion können erst im nächsten Zyklus erneut bearbeitet werden. Verschiedene Teile des Programms entwickeln sich effektiv parallel, solange sie nicht interagieren.
Infolgedessen ist ein Großteil des Codes der Synchronisation gewidmet, insbesondere der Verzögerung der Ausführung von Teilen des Programms bis zum richtigen Zeitpunkt. Es gibt viele Möglichkeiten, um Golf zu spielen, was dazu führt, dass Teile zu unlesbaren Blobs werden, die nur durch zyklisches Nachverfolgen ihrer Ausführung verstanden werden können.
Diese Taktiken werden im Folgenden nicht immer einzeln erwähnt:
)[A]
Verzögerungen A
für einen Zyklus. (Wahrscheinlich die einfachste und am besten lesbare Methode.)
~ef
tauscht die Elemente aus e
und f
verzögert damit auch deren Ausführung. (Wahrscheinlich die am wenigsten lesbare, bei geringfügigen Verzögerungen jedoch häufig die kürzeste.)
$1e
verzögert ein einzelnes Element e
.
-
und %
sind nützlich zum Verzögern von Zahlen (letztere für 0
und 1
.)
- Wenn Sie mehrere gleiche Elemente in einer Reihe verzögern
:
oder $
sie aus einem einzigen erstellen möchten.
(n
Umwicklungen n
in Klammern, die später nach Belieben entfernt werden können. Dies ist besonders wichtig für numerische Berechnungen, da Zahlen zu instabil sind, um überhaupt kopiert zu werden, ohne sie zuerst in einen Block zu setzen.
Gesamtstruktur
Der Rest der Erklärung ist in sieben Teile unterteilt, die sich jeweils auf einen Abschnitt des laufenden Programms beziehen. Die größeren Zyklen, nach denen sich die meisten von ihnen wiederholen, werden als "Iterationen" bezeichnet, um sie von den "Zyklen" einzelner Durchläufe durch die gesamte Warteschlange zu unterscheiden.
So teilt sich das ursprüngliche Programm auf:
A: )$$4255%%1(~
B: ):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
C:
D: (H-
E:
F:
G: ):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
Die große Zahl am Ende des Programms codiert den Rest in umgekehrter Reihenfolge, zwei Ziffern pro Zeichen, wobei 30 von jedem ASCII-Wert abgezogen werden (also z . B. 10
a (
.).
Auf einer höheren Ebene können Sie sich die Daten in diesem Programm (beginnend mit dem Bignum) als von rechts nach links fließend vorstellen, die Steuerung jedoch als von links nach rechts fließend. Auf einer niedrigeren Ebene verwirrt Fueue jedoch ständig die Unterscheidung zwischen Code und Daten.
- Abschnitt G dekodiert das Bignum in ASCII-Ziffern (z. B. Ziffer
0
als Ganzzahl 48
), wobei die niedrigstwertigen Ziffern zuerst abgespalten werden. Alle 15 Zyklen wird eine Ziffer ausgegeben.
- Abschnitt F enthält die erzeugten Ziffern-ASCII-Werte (jeweils innerhalb eines Blocks), bis Abschnitt E sie verbrauchen kann.
- In Abschnitt E werden die produzierten Ziffern zu je zwei verarbeitet, zu Blöcken des Formulars gepaart
[x[y]]
und auch die codierten Zeichen jedes Paares gedruckt.
- Abschnitt D besteht aus einem tief verschachtelten Block, der nach und nach aus den
[x[y]]
Blöcken so aufgebaut wird, dass alle Ziffern gedruckt und anschließend das gesamte Programm angehalten werden können.
- Abschnitt C behandelt den Bau von Abschnitt D und erstellt auch Abschnitt E neu.
- Abschnitt B erstellt Abschnitt C sowie sich selbst alle 30 Zyklen neu.
- Abschnitt A zählt die Zyklen bis zur letzten Iteration der anderen Abschnitte herunter. Dann bricht es Abschnitt B ab und führt Abschnitt D aus.
Abschnitt a
Abschnitt A behandelt die Planung des Programmendes. Es dauert 4258 Zyklen, um sich auf eine einzige Swap-Funktion zu reduzieren ~
, die dann eine Anpassung an Abschnitt B vornimmt, der seine Hauptschleife stoppt und stattdessen Abschnitt D ausführt.
)$ $4255% %1 (~
)$%%%...%% %0 [~]
)$%%%...% %1 [~]
⋮
)$ %0 [~]
) $1[~]
)[~]
~
- Eine
$
Funktion erstellt 4255 Kopien der folgenden Elemente, %
während (
die ~
in eckigen Klammern eingeschlossen sind.
- In jedem Zyklus wird der letzte
%
verwendet, um die folgende Zahl zwischen 0
und umzuschalten 1
.
- Wenn alle
%
s aufgebraucht sind, $1
wird 1 Kopie der [~]
(effektiv eine NOP) erstellt, und beim nächsten Zyklus werden )
die Klammern entfernt.
Abschnitt b
In Abschnitt B wird sowohl die Selbstregenerierung als auch eine neue Iteration von Abschnitt C alle 30 Zyklen durchgeführt.
) : [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] [BkB]
)$ $24% %0 :< [~:)~)] ~ [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] [BkB]
)$ %...%%% %1 < < [~:)~)] [BkB] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...%% %0 < [~:)~)[BkB]] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...% %1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
⋮
) $1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] (1)
~:) ~)[BkB] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
) : [BkB] ) [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] (2)
) [BkB] [BkB] $11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<
- A
:
dupliziert den folgenden großen Block (eine Kopie wird als abgekürzt [BkB]
) und )
entfernt dann die Klammern von der ersten Kopie.
$$24%%0
legt einen Countdown an, der dem in Abschnitt A ähnelt.
- Während dies abwärts zählt,
:<
wird es zu <<
einem und ~
tauscht zwei der Blöcke aus, wobei der Code für einen neuen Abschnitt C zuletzt platziert wird.
- Die beiden
<
Funktionen packen die beiden letzten Blöcke in den ersten - dies ist in normalen Iterationen überflüssig, ermöglicht jedoch, dass der ~
Ab-Abschnitt A am Ende seine Arbeit erledigt.
- (1) Wenn der Countdown beendet ist, werden
)
die äußeren Klammern entfernt. Next ~:)
wird zu ):
und ~)
tauscht a )
an den Anfang des Abschnitts C-Codes.
- (2) Abschnitt B befindet sich nun wieder in seinem Anfangszyklus, während a
)
gerade dabei ist, die Klammern zu entfernen, um eine neue Iteration von Abschnitt C auszuführen.
In der letzten Iteration erscheint ~
ab Abschnitt A unter Punkt (1) oben:
~ ) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] (1)
[~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] )
Die ~
vertauscht den )
Block in Abschnitt C, wodurch verhindert wird, dass Abschnitt B erneut ausgeführt wird.
Abschnitt C
In Abschnitt C werden neue Ziffernpaare in den Block von Abschnitt D eingefügt und neue Iterationen von Abschnitt E erstellt.
Das Folgende zeigt eine typische Iteration mit x
und die y
Darstellung der ASCII-Codes der Ziffern. In der allerersten Iteration sind die eingehenden "D" - und "E" -Elemente die ersten [H]
und -
stattdessen, da kein vorheriger Abschnitt E ausgeführt wurde, um Ziffernzeichenpaare zu erzeugen.
C D E
$11~ ) ~<[[+$4--498+*-:~-10)):])<~] [)))~] < [)))~[...]] [x[y]]
~~~ ~~~ ~~~ ~~) [[+$4--498+*-:~-10)):])<~] < [)))~] [)))~[...][x[y]]]
~~~ ~~~ ) ~ [[+$4--498+*-:~-10)):])<~] [)))~[)))~[...][x[y]]]]
~~~ ~ ) [)))~[....]] [[+$4--498+*-:~-10)):])<~]
~~[)))~[....]] )[[+$4--498+*-:~-10)):])<~]
[)))~[....]] ~[+$4--498+*-:~-10)):])<~
- Dabei wird eine andere Synchronisationsmethode verwendet, die ich für diese Antwort entdeckt habe. Wenn Sie mehrere Swap-Funktionen
~
in einer Reihe haben, wird die Reihe in jedem Zyklus auf ungefähr 2/3 verkleinert (da einer ~
zwei aufeinanderfolgende tauscht), aber gelegentlich mit einem Rest von ~
s, das Verwüstungen anrichtet, manipuliert sorgfältig das Folgende.
$11~
erzeugt eine solche Reihe. Der nächste ~
tauscht a <
über den folgenden Block. Ein anderer <
fügt am Ende einen neuen Ziffernpaarblock (Ziffern x und y als ASCII-Codes) in den Abschnitt D-Block ein.
- Im nächsten Zyklus hat die
~
Zeile einen ~~
Rest, der a ~
über Folgendes vertauscht )
. Der andere <
fügt Abschnitt D an einen [)))~]
Block an.
- Als nächstes
~
tauscht der Swap selbst den folgenden Block mit neuem Abschnitt-E-Code über den Abschnitt-D-Block. Dann ~
tauscht ein neuer Rest ein )
Kreuz aus, und schließlich tauscht der letzte ~~
in der ~
Reihe eines von ihnen in Abschnitt E aus, gerade als der )
seine Klammern entfernt hat.
In der letzten Iteration haben die Abschnitte A die Abschnitte B und C ~
vertauscht. )
Abschnitt C ist jedoch so kurzlebig, dass er bereits verschwunden ist und )
am Anfang von Abschnitt D endet.
Abschnitt D
In Abschnitt D wird die letzte große Zahl gedruckt und das Programm angehalten. Während des größten Teils des Programmablaufs handelt es sich um einen inerten Block, in dem die Abschnitte B – G beim Bauen zusammenarbeiten.
(H -
[H]-
⋮
[)))~[H-]] After one iteration of section C
⋮
[)))~[)))~[H-][49[49]]]] Second iteration, after E has also run
⋮
) [)))~[...]] [49[48]] Final printing starts as ) is swapped in
))) ~[...][49[48]]
)) )[49[48]] [...]
)) 49 [48][...] Print first 1
) )[48] [...]
) 48 [...] Print 0
)[...] Recurse to inner block
...
⋮
)[H-] Innermost block reached
H - Program halts
- Im ersten Zyklus des Programms wird
(
die Haltefunktion H
in eckige Klammern gesetzt. A -
folgt, es wird als Dummy-Element für die erste Iteration anstelle eines Ziffernpaares verwendet.
- Das erste reelle Ziffernpaar, das einbezogen wird
[49[49]]
, entspricht dem Finale 11
in der Ziffer.
- Das allerletzte digit Paar
[49[48]]
(entsprechend dem 10
am Anfang der Nummer) nicht tatsächlich in den Block eingearbeitet, aber dies macht keinen Unterschied , wie )[A[B]]
und )[A][B]
äquivalent ist, in beiden Dreh A[B]
.
Nach der letzten Iteration kommt der )
von Abschnitt B nach rechts getauschte Block an und der Block von Abschnitt D wird entsperrt. Am )))~
Anfang jedes Unterblocks wird sichergestellt, dass alle Teile in der richtigen Reihenfolge ausgeführt werden. Schließlich enthält der innerste Block ein H
Anhalten des Programms.
Abschnitt E
Abschnitt E behandelt das Kombinieren von ASCII-Ziffernpaaren, die von Abschnitt G erzeugt wurden, und beide drucken das entsprechende codierte Zeichen und senden einen Block mit dem kombinierten Paar nach links an die Abschnitte C und D.
Wiederum zeigt das Folgende eine typische Iteration mit x
und y
Darstellung der ASCII-Codes der Ziffern.
E F
~ [+$4--498+*-:~-10)):] ) < ~ [y] [x]
) [+$4--498+*-:~-10)):] < [x] [y]
+ $4- - 498 +*- :~ -10 ) ) : [x[y]]
+--- -{-498} +*- ~~{-10} ) ) [x[y]] [x[y]]
+-- - 498 +* -{-10} ~ ) x [y] [x[y]]
+- -{-498} + * 10 x )[y] [x[y]]
+ - 498 + {10*x} y [x[y]]
+ {-498} {10*x+y} [x[y]]
{10*x+y-498} [x[y]]
[x[y]]
- Die eingehenden Ziffernblöcke werden vertauscht, dann wird der y-Block an den x-Block angehängt und der gesamte Paarblock kopiert. Eine Kopie bleibt bis zum Ende für die Abschnitte C und D.
- Die andere Kopie wird erneut entsperrt, und dann wird eine Folge von arithmetischen Funktionen angewendet, um
10*x+y-498
den ASCII-Wert des codierten Zeichens zu berechnen . 498 = 10*48+48-30
, Die 48
rückgängig gemacht werden s die ASCII - Kodierung x
und y
während der 30
Verschiebungen der Codierung von 00–99
zu 30–129
, die alle druckbaren ASCII enthält.
- Die resultierende Zahl wird dann ausgeführt, wodurch das Zeichen gedruckt wird.
Abschnitt F
Abschnitt F besteht aus inerten Blöcken, die ASCII-Zifferncodes enthalten. Für den größten Teil des Programmablaufs gibt es hier höchstens zwei, da Abschnitt E sie mit derselben Geschwindigkeit verbraucht, mit der G sie erzeugt. In der letzten Druckphase 0
sammeln sich hier jedoch einige redundante Ziffern.
[y] [x] ...
Abschnitt G
Abschnitt G behandelt das Aufteilen der großen Zahl am Ende des Programms, wobei die niedrigstwertigen Ziffern zuerst angezeigt werden, und das Senden von Blöcken mit ihren ASCII-Codes nach links an die anderen Abschnitte.
Da es keine Unterbrechungsprüfung gibt, werden tatsächlich weiterhin 0
Ziffern erzeugt, wenn die Zahl auf 0 gesunken ist, bis Abschnitt D das gesamte Programm mit der H
Funktion anhält .
[BkG]
Kürzt eine Kopie des großen Startcode-Blocks ab, der zur Selbstreplikation verwendet wird, um neue Iterationen zu starten.
Initialisierung in den ersten Zyklen:
) :~ : [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] ( 106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
) ~ ~ [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] [BkG] [10...11]
) [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] ~ [BkG] [10...11]
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):] ~ : [10...11] [BkG]
Typische Iteration, N
bezeichnet die zu teilende Zahl:
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):] ~ : [N] [BkG]
) :~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+ :5 ) : [N] : [BkG]
) ~ ~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/] +5 5 ) [N] [N] [BkG] [BkG]
) [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/] ~ 10 N [N] [BkG] [BkG]
) ~:~ ~ ( [:~)*[):~[$1(+48]):~+]-:~~)10)~~] / N 10 [N] [BkG] [BkG]
) ~ : [:~)*[):~[$1(+48]):~+]-:~~)10)~~] ( {N/10} [N] [BkG] [BkG]
) [:~)*[):~[$1(+48]):~+]-:~~)10)~~] : [{N/10}] [N] [BkG] [BkG]
:~ )*[):~[$1(+48]):~+]- :~ ~)10 ) ~ ~ [{N/10}] [{N/10}] [N] [BkG] [BkG]
~~) *[):~[$1(+48]):~+]- ~~10 ) ) [{N/10}] ~ [{N/10}] [N] [BkG] [BkG]
) ~ * [):~[$1(+48]):~+] -10 ~ ) {N/10} [N] [{N/10}] [BkG] [BkG]
) [):~[$1(+48]):~+] * {-10} {N/10} ) [N] [{N/10}] [BkG] [BkG]
) :~ [$1(+48]) :~ + {-10*(N/10)} N [{N/10}] [BkG] [BkG]
) ~ ~ [$1(+48] ) ~ ~ {N%10} [{N/10}] [BkG] [BkG]
) [$1(+48] ~ ) {N%10} ~ [{N/10}] [BkG] [BkG]
$1( + 48 {N%10} ) [BkG] [{N/10}] [BkG]
( {48+N%10} BkG [{N/10}] [BkG] New iteration starts
[{48+N%10}] ....
- Der Delay-Blob ist hier besonders haarig. Allerdings ist der einzige neue Verzögerungs Trick zu verwenden ,
+:5
statt --10
eine Verzögerung 10
zwei Zyklen. Leider wurde nur einer der 10
s im Programm dadurch geholfen.
- Die Blöcke
[N]
und [BkG]
werden dupliziert, dann wird eine Kopie von N
durch geteilt 10
.
[{N/10}]
dupliziert wird, werden mehr arithmetische Funktionen verwendet, um den ASCII-Code der letzten Ziffer von N
as zu berechnen 48+((-10)*(N/10)+N)
. Der Block mit diesem ASCII-Code bleibt für Abschnitt F übrig.
- Die andere Kopie von
[{N/10}]
wird zwischen den [BkG]
Blöcken ausgetauscht , um den Start einer neuen Iteration einzurichten.
Bonus Quine (540 Bytes)
)$$3371%%1[~!~~!)!]):[)$$20%%0[):]~)~~[)$$12%%0[<$$7%~~0):~[+----48+*-~~10))]<]<~!:~)~~[40~[:~))~:~[)~(~~/[+--48):]~10]+30])):]]][)[H]](11(06(06(21(21(25(19(07(07(19(61(96(03(96(96(03(11(03(63(11(28(61(11(06(06(20(18(07(07(18(61(11(28(63(96(11(96(96(61(11(06(06(19(20(07(07(18(61(30(06(06(25(07(96(96(18(11(28(96(61(13(15(15(15(15(22(26(13(12(15(96(96(19(18(11(11(63(30(63(30(96(03(28(96(11(96(96(61(22(18(96(61(28(96(11(11(96(28(96(61(11(96(10(96(96(17(61(13(15(15(22(26(11(28(63(96(19(18(63(13(21(18(63(11(11(28(63(63(63(61(11(61(42(63(63
Probieren Sie es online!
Da ich mir nicht sicher war, welche Methode am kürzesten ist, habe ich zuerst versucht, Zeichen als zweistellige Zahlen zu codieren, die durch (
s getrennt sind . Der Kerncode ist etwas kürzer, aber die 50% größere Datendarstellung macht das wieder wett. Nicht so golfen wie der andere, da ich aufhörte, als mir klar wurde, dass es nicht besser werden würde. Es hat einen Vorteil: Es erfordert keine Implementierung mit Bignum-Unterstützung.
Die Gesamtstruktur ist der Hauptstruktur etwas ähnlich. Abschnitt G fehlt, da die Datendarstellung Abschnitt F direkt ausfüllt. Abschnitt E muss jedoch eine ähnliche Divmod-Berechnung durchführen, um die Ziffern der zweistelligen Zahlen zu rekonstruieren.