Завдання полягає в тому, щоб написати перекладача для нетипізованого обчислення лямбда якомога менше символів. Ми визначаємо нетипізоване обчислення лямбда так:
Синтаксис
Існують такі три види виразів:
Лямбда-вираз має форму,
(λ x. e)деxможе бути будь-яка юридична назва змінної таeбудь-яке юридичне вираження. Тутxназивається параметром іeназивається тілом функції.Для простоти ми додаємо ще одне обмеження, що не повинно бути змінної з тим самим назвою, що
xзараз в області застосування. А починає варіабельні бути в обсязі , коли з'являється його назва між(λі.і зупиняється , щоб перебувати в області видимості на відповідне).- Додаток до функції має форму,
(f a)деfіaє юридичними виразами. Тутfназивається функція іaназивається аргументом. - Змінна має форму,
xдеxє юридичною назвою змінної.
Семантика
Функція застосовується шляхом заміни кожного виникнення параметра в тілі функції його аргументом. Більш формально вираз форми ((λ x. e) a), де xє ім'ям змінної eі aє виразами, оцінює (або зменшує) вираз, e'де e'є результатом заміни кожного виникнення xв eна a.
Нормальна форма - це вираз, який далі неможливо оцінити.
Змагання
Якщо ви вирішите прийняти це, ваша місія полягає в тому, щоб написати інтерпретатора, який приймає за свій вклад вираз нетипізованого обчислення лямбда, що не містить вільних змінних, і створює як його вихід нормальну форму вираження (або вираз альфа-відповідний йому) . Якщо вираз не має нормальної форми або не є дійсним виразом, поведінка не визначена.
Виграє рішення з найменшою кількістю символів.
Пара приміток:
- Вхід може бути прочитаний зі stdin або з імені файлу, заданого як аргумент командного рядка (вам потрібно реалізувати лише те чи інше - не те й інше). Вихід йде на stdout.
- Крім того, ви можете визначити функцію, яка приймає вхід як рядок і повертає результат як рядок.
- Якщо символи, що не належать до ASCII, є для вас проблематичними, ви можете використовувати
\символ зворотної косої ( ) замість λ. - Ми підраховуємо кількість символів, а не байти, тому навіть якщо ваш вихідний файл кодується як unicode λ, вважається одним символом.
- Юридичні назви змінних складаються з однієї або декількох малих літер, тобто символів між a і z (не потрібно підтримувати буквено-цифрові імена, великі літери або не латинські літери - хоча це, звичайно, не може визнати недійсним ваше рішення).
- Що стосується цього завдання, жодні дужки не є обов'язковими. Кожен вираз лямбда та кожен додаток функції буде оточений рівно однією парою дужок. Жодне ім'я змінної не буде оточене дужками.
- Синтаксичний цукор, як писати
(λ x y. e)для(λ x. (λ y. e)), не потрібно підтримувати. - Якщо для оцінки функції потрібна глибина рекурсії більше 100, поведінка не визначена. Це повинно бути більш ніж низьким, щоб його можна було здійснити без оптимізації на всіх мовах і все ще достатньо великим, щоб можна було виконувати більшість виразів.
- Ви також можете припустити, що інтервал буде таким, як у прикладах, тобто немає пробілів на початку та в кінці вводу або перед a
λабо.та саме одним пробілом після a.та між функцією та її аргументом та після aλ.
Зразок введення та виведення
Вхід:
((λ x. x) (λ y. (λ z. z)))Вихід:
(λ y. (λ z. z))Вхід:
(λ x. ((λ y. y) x))Вихід:
(λ x. x)Вхід:
((λ x. (λ y. x)) (λ a. a))Вихід:
(λ y. (λ a. a))Вхід:
(((λ x. (λ y. x)) (λ a. a)) (λ b. b))Вихід:
(λ a. a)Вхід:
((λ x. (λ y. y)) (λ a. a))Вихід:
(λ y. y)Вхід:
(((λ x. (λ y. y)) (λ a. a)) (λ b. b))Вихід:
(λ b. b)Вхід:
((λx. (x x)) (λx. (x x)))Вихід: що завгодно (Це приклад виразу, який не має нормальної форми)
Вхід:
(((λ x. (λ y. x)) (λ a. a)) ((λx. (x x)) (λx. (x x))))Вихід:
(λ a. a)(Це приклад виразу, який не нормалізується, якщо ви оцінюєте аргументи перед викликом функції, і, на жаль, приклад, для якого моя спроба рішення не вдається)Вхід:
((λ a. (λ b. (a (a (a b))))) (λ c. (λ d. (c (c d)))))Вихід:
`(λ a. (λ b. (a (a (a (a (a (a (a (a b))))))))))Це обчислює 2 ^ 3 у церковних цифрах.
(\y. a).