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 esxsich um einen beliebigen legalen Variablennamen und einenebeliebigen legalen Ausdruck handeln kann. Hierxheißt der Parameter undeheiß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
xderzeit 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)wofundasind gesetzliche Ausdrücke. Hierfheißt die Funktion undaheißt das Argument. - Eine Variable hat die Form,
xbei derxes 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 xein Name ist variabel und eund asind Ausdrücke, bewertet (oder reduziert) auf den Ausdruck , e'wo e'das Ergebnis des Ersetzens jedes Auftreten xin emit 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).