Завдання полягає в тому, щоб написати перекладача для нетипізованого обчислення лямбда якомога менше символів. Ми визначаємо нетипізоване обчислення лямбда так:
Синтаксис
Існують такі три види виразів:
Лямбда-вираз має форму,
(λ 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)
.