Stackylogic ist eine logikbasierte Programmiersprache, die ich erfunden habe 0
und die Ein 1
- und Ausgänge für eine einzelne 0
oder 1
nach Fertigstellung enthält.
Ein Stackylogic-Programm besteht aus Zeilen, die nur die drei Zeichen 01?
sowie genau eines <
am Ende einer der Zeilen enthalten können. Zeilen dürfen nicht leer sein und die Zeile mit dem <
muss mindestens eins 0
haben 1
, oder ?
davor.
Hier ist ein Beispielprogramm, das (wie ich erklären werde) das NAND von zwei Bits berechnet :
1
?<
11
?
0
Jede Zeile in einem Stackylogic-Programm wird als Stapel betrachtet , mit dem unteren Rand links und dem oberen Rand rechts. Implizit steht ein leerer Stapel (leere Zeile) vor der ersten Zeile in einem Programm und nach der letzten Zeile.
Das Symbol <
, das wir als Cursor bezeichnen , markiert den Stack, auf dem gestartet werden soll, wenn ein Stackylogic-Programm ausgeführt wird. Die Ausführung eines Stackylogic-Programms erfolgt wie folgt:
Entfernen Sie das oberste Zeichen vom Stapel, auf den der Cursor gerade zeigt.
- Ist dies der Fall
?
, fordern Sie den Benutzer zur Eingabe von a0
oder a auf,1
und tun Sie so, als wäre dies der Charakter. - Wenn das Zeichen ist
0
, bewegen Sie den Cursor einen Stapel nach oben (bis zur Zeile über der aktuellen Zeile). - Wenn das Zeichen ist
1
, bewegen Sie den Cursor einen Stapel nach unten (in die Zeile unter der aktuellen Zeile).
- Ist dies der Fall
Wenn der Stapel, auf den sich der Cursor bewegt, leer ist, geben Sie den letzten Wert aus, der von einem Stapel abgefallen ist (immer ein
0
oder1
), und beenden Sie das Programm.Wenn der Stapel, auf den sich der Cursor bewegt, nicht leer ist, kehren Sie zu Schritt 1 zurück und wiederholen Sie den Vorgang.
Beachten Sie, dass Stackylogic-Programme immer enden, da sie ihre Stacks letztendlich entleeren müssen.
NAND-Beispiel
Im NAND-Programm startet der Cursor auf einem ?
:
1
?<
11
?
0
Wir werden die Benutzereingaben ein nehmen , 1
sobald die ?
aufgetaucht ist, was bedeutet , dass der Cursor nach unten bewegen wird, so dass das Programm wie folgt aussehen:
1
11<
?
0
Jetzt befindet sich eine Ebene 1
oben auf dem Cursorstapel. Es wird ordnungsgemäß geknallt und der Cursor bewegt sich erneut:
1
1
?<
0
Nehmen wir nun die Benutzereingaben 0
für an ?
, was bedeutet, dass sich der Cursor nach oben bewegt:
1
1<
0
Wieder 1
befindet sich a auf dem Cursorstapel, sodass der Cursor springt und sich nach unten bewegt:
1
<
0
Schließlich ist der Cursor-Stapel leer, so dass der letzte Wert 1
ausgegeben wird und das Programm endet.
Dies ist genau für ein NAND-Gatter, weil es 1 NAND 0
ist 1
. Dies funktioniert natürlich auch für die anderen drei Zwei-Bit-Eingänge, wenn Sie dies überprüfen möchten.
ODER Beispiel
Dieses Stackylogic-Programm simuliert ein ODER- Gatter:
?
?<
Es ist leicht zu erkennen, dass bei der ersten Eingabe von 1
der Cursor auf den impliziten leeren Stapel unterhalb der letzten Zeile bewegt wird, wodurch das Programm beendet und der 1
gerade eingegebene ausgegeben wird.
Bei einer Eingabe von 00
hingegen bewegt sich der Cursor zum impliziten leeren Stapel oben, beendet das Programm und gibt den zuletzt 0
eingegebenen aus.
Herausforderung
Schreiben Sie ein Programm oder eine Funktion, die ein Stackylogic-Programm als Zeichenfolge aufnimmt und es ausführt und das resultierende 0
oder ausgibt oder zurückgibt 1
.
Bei ?
können Sie den Benutzer zur Eingabe von a 0
oder 1
auffordern oder den Wert aus einer voreingestellten Zeichenfolge von 0
s und 1
s lesen, die Sie auch als Eingabe verwenden. (Dies kann eine weitere Zeichenfolge sein, die in Ihr Programm / Ihre Funktion eingegeben wird, oder Sie können einfach davon ausgehen, dass die erste oder letzte Zeile der Programmzeichenfolge der Eingabestream ist.)
Sie können davon ausgehen, dass das Programm und die Eingabe immer gut geformt sind. Sie können optional davon ausgehen, dass Eingabeprogramme mit einer einzelnen nachgestellten Zeile versehen sind (denken Sie jedoch daran, dass am Ende immer ein impliziter leerer Stapel steht).
Der kürzeste Code in Bytes gewinnt.
Weitere Beispielprogramme
ZERO
0<
ONE
1<
BUFFER
?<
NOT
1
?<
0
AND
?<
?
NAND
1
?<
11
?
0
OR
?
?<
NOR
1
?
00
?<
0
XOR(v1)
?
0
1?<
?
0
XOR(v2)
?
?<
11
?
0
XNOR(v1)
1
?
0?<
1
?
XNOR(v2)
1
?
00
?<
?
MEDIAN(v1)
1
???<
0
MEDIAN(v2)
?
1?<
??
quelle
?\1?<\??
. Alternativ ist hier eine symmetrische 5-Zeilen-Implementierung:?\?0\?<\?1\?
1\???<\0
.111\???????<\000
.Antworten:
Retina ,
79787368666563625544 BytesDie Anzahl der Bytes setzt die Kodierung nach ISO 8859-1 voraus.
Die Eingabe erfolgt über STDIN und wird als Benutzereingabe erwartet, die durch zwei Zeilenvorschübe vom Quellcode getrennt ist.
Probieren Sie es online! (Die ersten beiden Zeilen ermöglichen eine Testsuite, bei der jede Zeile ein separater Testfall mit
/
anstelle von Zeilenvorschüben ist.)Ich bin nicht ganz sicher, was hier passiert ist.
Das fühlt sich nach einer wirklich klobigen Lösung an unddas ist wirklich nicht das Problem, für das Retina gemacht wurde, aber es übertrifft aus irgendeinem Grund immer noch alle aktuellen Antworten.Erläuterung
Die endgültige Version davon war eigentlich ziemlich einfach.
Die erste Stufe ist einfach eine Schleife (aufgrund der
+
Option), die das eigentliche Interpretieren der Sprache durchführt. Die Stufe ist eine einzelne Regex-Substitution, aber tatsächlich sind es drei verschiedene Substitutionen, die in einer Stufe zusammengefasst sind, indem die Tatsache ausgenutzt wird, dass das Erfassen von Gruppen aus nicht verwendeten Zweigen während der Substitution einfach als leer betrachtet wird.Bearbeitung
?
:Dies nimmt einfach das erste Zeichen der Eingabe, stimmt dann mit beliebigen Zeichen überein, bis es gefunden wird
?<
, und setzt das erste Zeichen vor das<
(Löschen des?
).Bearbeitung
0
:Dies entspricht der Zeile vor a
0<
und setzt es nach dem<
Entfernen0
. (Tatsächlich löscht dies nur das0
und verschiebt die<
eine Zeile nach oben.)Bearbeitung
1
:Ziemlich dasselbe, außer dass wir
<
beim Löschen von a eine Zeile nach unten gehen1
. Ein wichtiges Detail, das zu beachten ist, ist die Verwendung von+
anstelle von*
, das heißt, wir verlangen, dass die nächste Zeile nicht leer ist.Der interessante Teil ist, herauszufinden, warum dies funktioniert und warum wir nicht den letzten Wert verfolgen müssen, den wir abgerufen haben, um die endgültige Ausgabe zu bestimmen. Dazu müssen wir uns überlegen, wie die obige Schleife enden kann. Da bei jeder möglichen Übereinstimmung die Zeichenfolge geändert wird (da mindestens ein Zeichen aus der Zeichenfolge entfernt wird), müssen nur Fälle berücksichtigt werden, in denen die Übereinstimmung insgesamt fehlschlägt.
Wenn das Zeichen vor
<
ist?
der einzige Weg für das Spiel zum Scheitern verurteilt ist , dass es nicht nicht-Zeilenvorschub - Zeichen überall vor ihm ist, aber das kann nicht geschehen , weil wir garantiert sind , dass immer genügend Eingang ist.Wenn das Zeichen vor "
<
is" steht0
, stimmt der reguläre Ausdruck immer überein, da sich immer eine weitere Zeile über der aktuellen befindet (dies kann die leere Zeile sein, die die Eingabe vom Quellcode trennt).Wenn das Zeichen vor "
<
ist" ist1
, schlägt der reguläre Ausdruck fehl, wenn wir uns entweder in der letzten Zeile befinden (da die Zeichen¶
nicht übereinstimmen) oder wenn die nächste Zeile leer ist (da die.+
Zeichen nicht übereinstimmen). Beachten Sie, dass in beiden Fällen das Programm nach dem Aufrufen von a beendet wird1
.Schließlich gibt es auch die Möglichkeit, dass
<
von keiner vorangeht?01
. Es hat sich herausgestellt, dass wir diese Situation nur erreichen können, indem wir0
auf eine leere Zeile aufspringen , sodass der Zeile<
jetzt ein Zeilenvorschub vorausgeht.Also, wenn das Programm auf einem beendet wird
1
,<
wird das immer noch danach sein1
. Wenn das Programm jedoch mit einem beendet wird0
, ist es in eine leere Zeile verschoben worden. Mit einer einfachen Match-Phase können wir diese Informationen leicht in die gewünschte Ausgabe umwandeln:Dies zählt einfach die Übereinstimmungen
1<
in der Zeichenfolge. Nach der obigen Überlegung wird dies der Fall sein,1
wenn das Programm auf einem beendet1
wird und0
wenn es auf einem beendet wird0
.quelle
Konvex ,
102 bis95 BytesNun, eine Liste von stapelbasierten Sprachen, die in einer stapelbasierten Sprache codiert sind, stellte sich als ziemlich schwierig heraus.
Markiere meine Worte: Ich werde das auf 100 Bytes oder weniger bringen!EDIT: Erfolg!Probieren Sie es online!
Die Programmeingabe erfolgt über Befehlszeilenargumente. Geben Sie
0
s und1
s normalerweise ein (bei TIO bedeutet dies Zeilenumbruch im Feld "Eingabe").Erläuterung:
Der gesamte Code kann in drei Teile aufgeteilt werden:
Dieses Bit nimmt einfach das Eingabeprogramm und konvertiert es in ein Array von Zeilen und fügt außerdem
" "
Zeilen am Anfang des Arrays hinzu. Da die Arrays von Convex umgebrochen werden, reicht es aus, am Anfang nur einen leeren Stapel zu haben.Dieser Teil bestimmt, mit welcher Zeile (oder mit welchem Stapel) die Ausführung gestartet werden soll. Es durchsucht jede Zeile und gibt die richtige Stack-Nummer in die
M
Variable ein.Das ist das lustige Stück! Es wird so lange wiederholt, bis es eine Zeile mit nur einem Leerzeichen (
" "
) erreicht (Symbol für einen leeren Stapel). Wenn die Zeile nicht leer ist, geschieht Folgendes:?
, nehmen Sie die Eingabe vor und hängen Sie das Zeichen an die Zeile an.0
, bewegen Sie den Zeilenzeiger um eins nach oben.1
, bewegen Sie den Zeilenzeiger um eins nach unten.(Leerzeichen) ist, drucken Sie das zuletzt angezeigte Element und beenden Sie das Programm.
quelle
32-Bit-x86-Computercode, 70 Byte
In hex:
Die Eingabe ist eine NULL-terminierte mehrzeilige Zeichenfolge (durch Zeilenvorschub getrennt), die über ESI übergeben wird. Es wird angenommen, dass die Benutzereingabe die erste Zeile ist. Gibt '0' / '1' in AL zurück.
Demontage:
quelle
JavaScript (ES6), 136
138Annehmen eines abschließenden Zeilenumbruchs im Programm
Weniger golfen
Prüfung
quelle
05AB1E ,
58565553515046 Bytes2 Bytes gespart dank Emigna ! Code:
Verwendet die CP-1252- Codierung. Probieren Sie es online! .
quelle
Python 3,
147146145144 Bytes1 Byte danke an @Lynn.
quelle
Python 3, 318
F ist das Programm, z wird eingegeben. Ja, meine Variablennamen sind verrückt.
quelle
ES6, 190 Bytes
Verwenden Sie wie
f(program, input)
quelle
[...o]
anstelle vono.split``
und verwenden Siefor
anstelle vonwhile
, damit Sie zwei Ausdrücke in diefor
sparenden zwei Bytes verschieben können. Ein paar konkrete Tipps: Ich denke, IhreNumber
Besetzung ist unnötig, da die*2
Besetzung für Sie bestimmt ist, und ich würde einfach lesen,i
indem ichj=0
undi[j++]
was ich denke, spart 11 Bytes.f=
, anonyme Funktionen sind erlaubt.Java,
256255231219215213 BytesDemo auf Ideone.
Nimmt das Programm und die Eingabe als Argumente und gibt das Ergebnis als Ganzzahl zurück.
quelle
for
Schleife geändert , aber was bedeutet Ihr erster Kommentar?int f(String[]I)...
und du kannst derString[]p=I.split("\n");
int f(String[]P)
->(String[]I){...
PHP (<7,0),
195192 BytesNimmt das Programm als erstes Argument und jeden Wert als zusätzliches Argument.
Beachten Sie, dass ich dies mit split ("", ..) als Leerzeichen und nicht mit Zeilenumbrüchen getestet habe, aber es sollte trotzdem funktionieren.
Gibt einen veralteten Hinweis, wenn in PHP> 5.3 ausgeführt.
Gibt auch eine Warnung aus, wenn Sie das Programm verlassen. Es funktioniert jedoch immer noch und wird korrekt ausgegeben, sodass es in Ordnung ist.
quelle
C
264249244242C kann nicht so gut mit Strings umgehen, aber das ist ziemlich kurz.
Sie scannt die Zeichenfolge nach dem Cursor (
<
), bewegt sich 1 Stelle zurück, liest den Befehl, ersetzt ihn durch eintab
Zeichen und bewegt sich entweder eine Zeile vorwärts oder rückwärts. Die Eingabe erfolgt in Form eines C char-Arrayschar array[]="1\n?<\n11\n?\n0";result = f(array);
, obwohl auch Wagenrückläufe zulässig sind.Obwohl die Eingabezeichenfolge geändert wird, wird die Länge nicht geändert.
Testprogramm
Führen Sie dieses Programm mit jedem Testfall als separaten Parameter aus, wobei Sie anstelle von Zeilenumbrüchen einen einzelnen Backslash verwenden. Testfälle werden durch eine Leerzeile getrennt.
quelle