Zusammenfassung? Das ist meine Stärke!

18

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 LETAnweisung können Sie ihnen neue Werte zuweisen.

Zum Beispiel wird nach der Ausführung LET 2=4-1von nun an 2der Wert von angenommen 3, was bedeutet, dass der Wert, wenn 2er in einem Ausdruck auftaucht, stattdessen durch "ersetzt" wird 3. Der Ausdruck (1+1)*2wü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- LETAusdrü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 , 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
Löwe
quelle
Ist 0eine gültige Nummer?
Orlp
@orlp 0ist gültig ("Zahlen werden immer nicht negative ganze Zahlen sein")
Leo
Sollten wir arithmetische Operatoren akzeptieren?
Bacchusbeale
@ Bacchusbeale Nein, nur Summation.
Leo
Gibt es eine bestimmte maximale Anzahl oder ist sie so groß wie der native Integer-Typ der Sprache? Es wäre auch eine ungültige Ausgabe, eine Liste von Zahlen zurückzugeben, von denen eine das Ergebnis ist, oder? (zum Beispiel das Wörterbuch / die Karte
ausdrucken,

Antworten:

4

Gelee , 28 Bytes

®y$ÐL
ṪÇ+Ç¥/Ṅ;®⁸Ǥ;©
⁸©ḷƓÇ€¤

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:

[[5,[4]],[6,[5]],[7,[1,2,5]],[7,[5,2,1]],[18,[5,6,7]],[5,[3]],[10,[6,4]]]

Erläuterung

Hilfsfunktion 1Ŀ (eine Ganzzahl in ihren Wert übersetzen)

®y$ÐL
   ÐL   Repeatedly, until there are no further changes,
  $       apply the following unary function to {the input}:
 y          replace values using the mapping table
®             stored in the register.
        {Then return the eventual result.}

Diese Hilfsfunktion funktioniert auf Grund der Art und Weise, ywie 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)

ṪÇ+Ç¥/Ṅ;®⁸Ǥ;©
Ṫ               On the last element of {the input},
 Ç              Run 1Ŀ,
     /          left fold it via
    ¥             the following binary function:
  +                 add {the two arguments}
   Ç                and run 1Ŀ on {the result},
      Ṅ         write {the result} (and a newline) to standard output,
       ;®       append the value of the register,
            ;   prepend
           ¤      the following value:
         ⁸          {the input, without its last element}
          Ç         with 1Ŀ run on it
             ©  and store that value in the register {and return it}.

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

⁸©ḷƓÇ€¤
 ©       Initialize the mapping table
⁸        with the empty string (which is also the empty list)
  ḷ      then evaluate and discard
      ¤  the following value:
   Ɠ       a line from standard input, parsed into a data structure
    Ç€     with each element transformed via 2Ŀ
         {and leave the empty string to be printed implicitly}

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 von 0, der abstürzt y), 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 wird 2Ḷ.


quelle
5

Perl 5 , 92 Bytes

90 Byte Code + -plFlags.

sub f{($b=$h{$a=pop}//$a)!=$a?f($b):$a}s%(\d+)\+(\d+)%f($1)+f$2%e&&redo;/=/;$_=$h{f$`}=f$'

Probieren Sie es online!

Ich verwende die Hashtabelle %h, um die Zuordnung zwischen Zahlen zu speichern.
Die Funktion ( sub) fgibt 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, //$aist 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 wir fdie Eingabe entweder rekursiv auf oder geben sie zurück.
Das Hauptprogramm besteht aus zwei Schritten:
- s%(\d+)\+(\d+)%f($1)+f$2%e&&redoWertet die erste Addition auf der rechten Seite aus, während es noch eine Addition gibt: Sie wird x+ydurch das Ergebnis der Bewertung von ersetzt f(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.

Dada
quelle
5

JavaScript (Node.js) , 81 Byte

v=x=>(v[x]=v[x]||x,v[x]-x?v(v[x]):x)
f=x=>l=>v[v(x)]=l.reduce((p,x)=>v(v(x)+p),0)

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.

vwird als Funktion zum Berechnen des aktuellen Istwerts einer Zahl und als Objekt zum Speichern der Istwerte verwendet. Zunächst wird v[x]=v[x]||xdafür gesorgt, dass v[x]definiert wird. v[x]-xführt einen Vergleich durch, um festzustellen, ob dies die tatsächliche Anzahl ist oder nicht. Wenn sich die Nummer nicht selbst v(v[x])zuordnen lässt, versuchen Sie es erneut, andernfalls kehren Sie zurück x.

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.

OinkIguana
quelle
3

Haskell , 116 113 108 106 Bytes

(#)=until=<<((==)=<<)
e?((n,s):r)|m<-foldl1(\a b->e#(e#a+e#b))s=m:(\x->last$m:[e#x|x/=e#n])?r
e?r=[]
(id?)

Probieren Sie es online! Jede Gleichung 4=3+1+5wird 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 Funktion eund einen Startwert zu finden x.

Die Funktion ?übernimmt eine Auswertungsfunktion eund löst jede Gleichung rekursiv. foldl1(\a b->e#(e#a+e#b))swertet die rechte Seite einer Gleichung aus und speichert das Ergebnis mzB für 4=3+1+5Berechnungen eval(eval(eval 3 + eval 1) + eval 5), wobei jede evaleine Fixpunktanwendung von ist e. Dann wird die Auswertungsfunktion geändert, um die neue Zuordnung von nzu 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 idbildet jede Ganzzahl auf sich selbst ab.


Dank an Ørjan Johansen für eine kürzere Fixpoint-Funktion, die 2 Bytes einspart!

Laikoni
quelle
Gute Arbeit! Durch die Art und Weise Sie alle Zwischenergebnisse zurück erforderlich sind, so dass Sie fallen könnenlast.
Leo
2
(#)e=until((==)=<<e)eoder (#)=until=<<((==)=<<)ist kürzer.
Ørjan Johansen
@ ØrjanJohansen Vielen Dank!
Laikoni
3

ok, 48 bytes

a:[];s:{*(a@x;x)^0N}/;f:{a[s@x]:y:{s@x+y}/s'y;y}

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 0bis 998, dann reichen die folgenden Werte aus ( 41 Byte ± einige wenige, abhängig vom Maximum):

a:!999;s:(a@)/;f:{a[s@x]:y:{s@x+y}/s'y;y}

Erläuterung:

; trennt drei Definitionen.

aist 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 Zahlen 0zu 998.

sist 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 fbedeutet, dass:

f:{                      } /function called f, input number x, list y
                    s'y    /apply s to every number in the list
                   /       /fold through the list
            {s@x+y}        /    sum the two numbers, apply s
   a[s@x]:                 /set the s(x) to map to the final sum
          y:           ;y  /redefine y to be the final sum, then return it
zgrep
quelle
3

Python 3, 146 132 130 Bytes

14 Bytes gespeichert dank @Dada
2 Bytes gespeichert dank @ mbomb007

d={}
g=lambda x:d.get(x)and x!=d[x]and g(d[x])or x
def f(t):
 for n,(s,*r)in t:
  for b in r:s=g(g(s)+g(b))
  d[g(n)]=s;yield g(n)

Probieren Sie es online!

Empfängt Eingaben als Tupel von Gleichungen [ x = y + z + wals (x, (y, z, w))], gibt sie über einen Generator aus.

Uriel
quelle
Können Sie ein Aufrufbeispiel zeigen, damit es getestet werden kann?
Leo
1
@Leo hat TIO hinzugefügt.
Uriel
1
gkönnte wahrscheinlich geschrieben werden g=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! ).
Dada
1
@ Dada danke!
Uriel
1
Kein Einzug mit halben Leerzeichen, aber ein weiterer guter Trick ist die Verwendung eines einzelnen Tabulators anstelle von zwei Leerzeichen. Solange Einrückungen unterschiedlich sind, ist Python zufrieden (Sie können beispielsweise die Tabulatortaste und die Tabulatortaste als Einrückungen in zusätzlichen verschachtelten Ebenen verwenden). Dies kann Ihnen zwei Bytes sparen :)
Leo