Die Herausforderung besteht darin, einen Interpreter für die untypisierte Lambda-Rechnung mit möglichst wenigen Zeichen zu schreiben . Wir definieren den untypisierten Lambda-Kalkül wie folgt:
Syntax
Es gibt die folgenden drei Arten von Ausdrücken:
Ein Lambda-Ausdruck hat die Form,
(λ x. e)
bei der esx
sich um einen beliebigen legalen Variablennamen und einene
beliebigen legalen Ausdruck handeln kann. Hierx
heißt der Parameter unde
heißt der Funktionskörper.Der Einfachheit halber fügen wir die weitere Einschränkung hinzu, dass es keine Variable mit demselben Namen geben darf, wie
x
derzeit im Gültigkeitsbereich. Eine Variable beginnt im Gültigkeitsbereich zu sein, wenn ihr Name zwischen(λ
und erscheint, und.
endet am entsprechenden Gültigkeitsbereich)
.- Funktionsanwendung hat die Form
(f a)
wof
unda
sind gesetzliche Ausdrücke. Hierf
heißt die Funktion unda
heißt das Argument. - Eine Variable hat die Form,
x
bei derx
es sich um einen zulässigen Variablennamen handelt.
Semantik
Eine Funktion wird angewendet, indem jedes Vorkommen des Parameters im Funktionskörper durch sein Argument ersetzt wird. Formal ein Ausdruck der Form ((λ x. e) a)
, in dem x
ein Name ist variabel und e
und a
sind Ausdrücke, bewertet (oder reduziert) auf den Ausdruck , e'
wo e'
das Ergebnis des Ersetzens jedes Auftreten x
in e
mit a
.
Eine Normalform ist ein Ausdruck, der nicht weiter ausgewertet werden kann.
Die Herausforderung
Ihre Mission ist es, einen Interpreter zu schreiben, der als Eingabe einen Ausdruck des untypisierten Lambda-Kalküls ohne freie Variablen verwendet und als Ausgabe die Normalform des Ausdrucks (oder einen Ausdruck, der Alpha-Kongruenz zu ihm aufweist) erzeugt. . Wenn der Ausdruck keine normale Form hat oder kein gültiger Ausdruck ist, ist das Verhalten undefiniert.
Die Lösung mit der geringsten Anzahl von Zeichen gewinnt.
Ein paar Notizen:
- Die Eingabe kann entweder von stdin oder von einem Dateinamen als Befehlszeilenargument gelesen werden (Sie müssen nur das eine oder das andere implementieren - nicht beide). Die Ausgabe erfolgt nach stdout.
- Alternativ können Sie eine Funktion definieren, die die Eingabe als Zeichenfolge verwendet und die Ausgabe als Zeichenfolge zurückgibt.
- Wenn für Sie Nicht-ASCII-Zeichen problematisch sind, können Sie
\
anstelle von λ den Backslash ( ) verwenden. - Wir zählen die Anzahl der Zeichen, nicht die Bytes. Selbst wenn Ihre Quelldatei als Unicode kodiert ist, zählt λ als ein Zeichen.
- Zulässige Variablennamen bestehen aus einem oder mehreren Kleinbuchstaben, dh Zeichen zwischen a und z (alphanumerische Namen, Großbuchstaben oder nicht-lateinische Buchstaben müssen nicht unterstützt werden - dies macht Ihre Lösung jedoch nicht ungültig).
- In Bezug auf diese Herausforderung sind keine Klammern optional. Jeder Lambda-Ausdruck und jede Funktionsanwendung wird von genau einem Klammerpaar umgeben. Kein Variablenname wird in Klammern gesetzt.
- Syntaktischer Zucker wie das Schreiben
(λ x y. e)
für(λ x. (λ y. e))
muss nicht unterstützt werden. - Wenn eine Rekursionstiefe von mehr als 100 erforderlich ist, um eine Funktion auszuwerten, ist das Verhalten undefiniert. Das sollte mehr als niedrig genug sein, um ohne Optimierung in allen Sprachen implementiert zu werden und dennoch groß genug, um die meisten Ausdrücke ausführen zu können.
- Sie können auch davon ausgehen, dass der Abstand wie in den Beispielen ist, dh keine Leerzeichen am Anfang und Ende der Eingabe oder vor einem
λ
oder.
genau einem Leerzeichen nach einem.
und zwischen einer Funktion und ihrem Argument und nach einemλ
.
Sample Input und Output
Eingang:
((λ x. x) (λ y. (λ z. z)))
Ausgabe:
(λ y. (λ z. z))
Eingang:
(λ x. ((λ y. y) x))
Ausgabe:
(λ x. x)
Eingang:
((λ x. (λ y. x)) (λ a. a))
Ausgabe:
(λ y. (λ a. a))
Eingang:
(((λ x. (λ y. x)) (λ a. a)) (λ b. b))
Ausgabe:
(λ a. a)
Eingang:
((λ x. (λ y. y)) (λ a. a))
Ausgabe:
(λ y. y)
Eingang:
(((λ x. (λ y. y)) (λ a. a)) (λ b. b))
Ausgabe:
(λ b. b)
Eingang:
((λx. (x x)) (λx. (x x)))
Ausgabe: alles (Dies ist ein Beispiel für einen Ausdruck ohne normale Form)
Eingang:
(((λ x. (λ y. x)) (λ a. a)) ((λx. (x x)) (λx. (x x))))
Ausgabe:
(λ a. a)
(Dies ist ein Beispiel für einen Ausdruck, der sich nicht normalisiert, wenn Sie die Argumente vor dem Funktionsaufruf auswerten, und leider ein Beispiel, für das mein Lösungsversuch fehlschlägt.)Eingang:
((λ a. (λ b. (a (a (a b))))) (λ c. (λ d. (c (c d)))))
Ausgabe:
`(λ a. (λ b. (a (a (a (a (a (a (a (a b))))))))))
Dies berechnet 2 ^ 3 in Zahlen der Kirche.
(\y. a)
.