Einführung
Forte ist eine sehr eigenartige esoterische Sprache, die auf dem Konzept der Änderung der Zahlenwerte basiert. In Forte-Zahlen sind keine Konstanten, sondern Variablen. Mit der LET
Anweisung können Sie ihnen neue Werte zuweisen.
Zum Beispiel wird nach der Ausführung LET 2=4-1
von nun an 2
der Wert von angenommen 3
, was bedeutet, dass der Wert, wenn 2
er in einem Ausdruck auftaucht, stattdessen durch "ersetzt" wird 3
. Der Ausdruck (1+1)*2
würde jetzt zu auswerten 9
.
Diese Anweisung in Forte wird sowohl zum Speichern von Informationen als auch zur Flusssteuerung verwendet (Zeilen sind nummeriert und durch Ändern des Werts ihrer Nummern können Sie die Reihenfolge ihrer Ausführung bestimmen). In dieser Herausforderung werden wir uns nicht mit diesem zweiten Aspekt befassen.
Die Herausforderung
Sie müssen einen Interpreter für eine vereinfachte Teilmenge der Forte- LET
Ausdrücke schreiben .
Sie erhalten als Eingabe eine Reihe von Zeilen, die dieser Grammatik entsprechen:
<line>::= <number>=<expression>
<expression>::= <number>|<expression>+<number>
Hinweis: Diese Grammatik ist ungültig, da Zeilennummern, LET und Klammern fehlen (diese sind immer obligatorisch).
Das heißt, Sie müssen sich nur mit dem Berechnen von Summierungen und dem Zuweisen von Werten zu Zahlen befassen. Klammern sind in der Eingabe nicht vorhanden, und jeder Ausdruck muss von links nach rechts ausgewertet werden. Beachten Sie, dass Teilergebnisse von Neudefinitionen betroffen sind!
Zahlen sind immer nicht negative Ganzzahlen, bis zur Grenze des nativen Ganzzahltyps Ihrer Sprache (oder 2 ^ 32, je nachdem, welcher Wert höher ist).
Für jede Zeile sollten Sie das Ergebnis des Ausdrucks ausgeben und dieses Ergebnis dem (möglicherweise neu zugewiesenen) Wert der ersten Zahl zuweisen, was sich auf die Interpretation der folgenden Zeilen auswirkt.
Das ist Code-Golf , der kürzeste Code (in Bytes) gewinnt!
Andere Regeln
- Das Eingabeformat ist flexibel. Sie können beispielsweise eine einzelne Zeichenfolge mit Zeilenumbrüchen, eine Liste mit Zeichenfolgen und eine Liste mit Zahlen verwenden. Dasselbe gilt für die Ausgabe, sofern klar ist, was das Ergebnis der einzelnen Ausdrücke in ist die Eingabe.
- Sie können entweder eine Funktion, ein vollständiges Programm oder eine Lösung einreichen, die in einer REPL-Umgebung ausgeführt werden soll, indem Sie sie für jede Zeile einmal aufrufen.
- Standardlücken sind verboten, insbesondere können Sie in Ihrem Code keinen externen Forte-Interpreter aufrufen.
Beispiele
Diese sind alle Teil derselben Eingabe. Nach jeder Zeile wird die erwartete Ausgabe im Verhältnis zu dieser Zeile angezeigt, manchmal mit einem Kommentar, der relevante Neuzuweisungen angibt (nicht Teil der erforderlichen Ausgabe).
5=4
4
6=5
4 # 5 -> 4
7=1+2+5
7
7=5+2+1
4 # Order of operations matters! 5+2 -> 4+2 -> 6 -> 4
18=5+6+7
12
5=3
3 # Remember: 5 -> 4
10=6+4
3 # 6 -> 4 -> 3, 3+3 = 6 -> 3
0
eine gültige Nummer?0
ist gültig ("Zahlen werden immer nicht negative ganze Zahlen sein")Antworten:
Gelee , 28 Bytes
Probieren Sie es online!
Dies ist eines der wenigen Jelly-Programme, bei denen es anscheinend knapper ist, Eingaben von Standardeingaben zu übernehmen. Es ist ein vollständiges Programm (das Schreiben einer Funktion wäre kürzer gewesen, wird jedoch von den PPCG-Regeln verboten, da es beim zweiten Mal nicht korrekt ausgeführt wird). Das Eingabeformat sieht folgendermaßen aus:
Erläuterung
Hilfsfunktion
1Ŀ
(eine Ganzzahl in ihren Wert übersetzen)Diese Hilfsfunktion funktioniert auf Grund der Art und Weise,
y
wie sie definiert ist , entweder für einen einzelnen Wert oder für eine Liste von Werten korrekt . Wenn für einen einzelnen Wert mehr als eine Zuordnung angegeben ist, wird die erste Zuordnung aus der Tabelle übernommen. Die Zuordnungstabelle wird im Register gespeichert (das im Grunde genommen nur eine Variable ist; Jelly hat nur eine Variable).Hilfsfunktion
2Ŀ
(eine LET-Anweisung auswerten)Wir wollen hier nicht wirklich einen Rückgabewert; Wir führen dies nur aufgrund der Nebenwirkungen durch (Aktualisierung des Registers und Ausgabe des zugewiesenen Werts). Jelly-Funktionen geben jedoch immer einen Wert zurück, sodass wir nur die Zuordnungstabelle zurückgeben lassen, da dies am genauesten ist.
Hauptprogramm
Normalerweise
⁸
würde uns das erste Befehlszeilenargument angezeigt, wenn es in diesem Kontext ausgeführt wird. Es gibt jedoch kein Argument (wir nehmen Eingaben von der Standardeingabe). Daher wird es in einem alternativen Modus ausgeführt, in dem wir die Nullzeichenfolge erhalten. Die Notwendigkeit, das Register zu initialisieren (von seinem Standardwert von0
, der abstürzty
), bedeutet, dass wir die Benutzereingabe nicht implizit erwähnen können , was bedeutet, dass es so billig ist, es von der Standardeingabe (Ɠ
) zu nehmen, wie es wäre, es von a zu nehmen Befehlszeilenargument (³
oder⁸
) und der Zugriff auf die alternative Verwendung von⁸
bedeutet, dass die ungewöhnliche (für Jelly) Eingabeform tatsächlich ein Byte kürzer ist.Es ist möglich, dass dies verbesserungsfähig ist. Ich habe noch nicht herausgefunden, warum die zweite Zeile Bedürfnisse zu sagen und
⁸Ǥ;
nicht nur;@Ç
- die beiden gleichwertig sein sollte, soweit ich Jelly verstehen, angesichts der fehlenden Verwendung vonµ
/ð
/ø
- aber die letztere Abstürze aus irgendeinem Grund. Ebenso gibt es verschiedene andere Möglichkeiten, das Programm neu zu ordnen, ohne Bytes zu verlieren. Es ist also möglich, dass ich eine Möglichkeit verpasst habe, die Dinge etwas kürzer zu machen.Übrigens: Wenn Sie
ḷ
in der letzten Zeile;
den Wert ändern , erhalten Sie einen interessanten Einblick in die internen Abläufe des Programms, da dann der "Verlauf des Registers" ausgegeben wird, der implizit durch die Rückgabewerte von ausgegeben wird2Ḷ
.quelle
Perl 5 , 92 Bytes
90 Byte Code +
-pl
Flags.Probieren Sie es online!
Ich verwende die Hashtabelle
%h
, um die Zuordnung zwischen Zahlen zu speichern.Die Funktion (
sub
)f
gibt die Nummer zurück, auf die ihre Eingabezuordnung (oder ihre Eingabe, wenn sie keiner Nummer zugeordnet ist):$h{$a=pop}
Ruft die Nummer ab, zu der die Eingabezuordnung gehört. Ist dies nicht der Fall,//$a
ist der Wert von($b=$h{$a=pop}//$a)
input ($a
). Wir stellen sicher, dass dieser Wert nicht die Eingabe selbst ist, um keine Endlosschleife zu erzeugen (!=$a
). Dann rufen wirf
die Eingabe entweder rekursiv auf oder geben sie zurück.Das Hauptprogramm besteht aus zwei Schritten:
-
s%(\d+)\+(\d+)%f($1)+f$2%e&&redo
Wertet die erste Addition auf der rechten Seite aus, während es noch eine Addition gibt: Sie wirdx+y
durch das Ergebnis der Bewertung von ersetztf(x)+f(y)
.-
/=/;$_=$h{f$`}=f$'
erledigt die Aufgabe:/=/
ermöglicht den Zugriff auf die linke Seite mit$`
und die rechte Seite mit$'
, dann$h{f$`}=f$'
erfolgt die Zuordnung. Und wir weisen es auch zu$_
, das implizit nach jeder Zeile gedruckt wird.quelle
JavaScript (Node.js) , 81 Byte
Probieren Sie es online!
Erhält Eingaben, indem f mit dem Wert aufgerufen wird, dem es zugewiesen werden soll, und anschließend das Ergebnis mit einem Array von Werten aufgerufen wird, die addiert werden sollen. (dh
f(5)([4])
) Wiederholen Sie dies für mehrere Zeilen.v
wird als Funktion zum Berechnen des aktuellen Istwerts einer Zahl und als Objekt zum Speichern der Istwerte verwendet. Zunächst wirdv[x]=v[x]||x
dafür gesorgt, dassv[x]
definiert wird.v[x]-x
führt einen Vergleich durch, um festzustellen, ob dies die tatsächliche Anzahl ist oder nicht. Wenn sich die Nummer nicht selbstv(v[x])
zuordnen lässt, versuchen Sie es erneut, andernfalls kehren Sie zurückx
.f
führt die Berechnung und Zuweisung durch, die durchgeführt wird, um ein Byte zu sparen, wobei der zweite Aufruf den berechneten Wert zurückgibt.quelle
Haskell ,
116 113 108106 BytesProbieren Sie es online! Jede Gleichung
4=3+1+5
wird als Tupel notiert(4,[3,1,5])
. Die anonyme Funktion erstellt(id?)
eine Liste solcher Tupel und gibt eine Liste aller Zwischenergebnisse zurück.#
ist eine Funktion, um einen Fixpunkt einer bestimmten Funktione
und einen Startwert zu findenx
.Die Funktion
?
übernimmt eine Auswertungsfunktione
und löst jede Gleichung rekursiv.foldl1(\a b->e#(e#a+e#b))s
wertet die rechte Seite einer Gleichung aus und speichert das Ergebnism
zB für4=3+1+5
Berechnungeneval(eval(eval 3 + eval 1) + eval 5)
, wobei jedeeval
eine Fixpunktanwendung von iste
. Dann wird die Auswertungsfunktion geändert, um die neue Zuordnung vonn
zu berücksichtigen:(\x->last$m:[e#x|x/=e#n])
Dies ist dasselbe wie\x -> if x == eval n then m else eval x
.Die anfängliche Auswertungsfunktion
id
bildet jede Ganzzahl auf sich selbst ab.Dank an Ørjan Johansen für eine kürzere Fixpoint-Funktion, die 2 Bytes einspart!
quelle
last.
(#)e=until((==)=<<e)e
oder(#)=until=<<((==)=<<)
ist kürzer.ok, 48 bytes
Verwendung:
f[5;1 2 3] / 5=1+2+3
Probieren Sie es online!
Wenn es Ihnen nichts ausmacht, eine Obergrenze für die Zahlen festzulegen, die Sie verwenden können, z. B. nur Zahlen
0
bis998
, dann reichen die folgenden Werte aus ( 41 Byte ± einige wenige, abhängig vom Maximum):Erläuterung:
;
trennt drei Definitionen.a
ist ein Wörterbuch / eine Karte von Zahlen. Im ersten Fall ist es eine tatsächliche, leere Wörterbuch[]
, im zweiten Fall ist es eine Liste der Zahlen0
zu998
.s
ist eine Funktion, die die "resultierende" Nummer findet, wenn eine Nummer vergeben wird. Das/
am Ende der Funktion bedeutet, dass es sich auf seinen eigenen Ausgang bezieht, bis sich der Ausgang nicht mehr ändert.Das letzte Bit
f
bedeutet, dass:quelle
Python 3,
146132130 Bytes14 Bytes gespeichert dank @Dada
2 Bytes gespeichert dank @ mbomb007
Probieren Sie es online!
Empfängt Eingaben als Tupel von Gleichungen [
x = y + z + w
als(x, (y, z, w))
], gibt sie über einen Generator aus.quelle
g
könnte wahrscheinlich geschrieben werdeng=lambda x:d.get(x)and d[x]!=x and g(d[x])or x
. Und ich denke, Sie können 1 Leerzeichen anstelle von 2 einrücken. Das sollte Sie auf [132 Bytes] bringen ( Online ausprobieren! ).