Исчисление SKI вариант исчисления лямбда , который не использует лямбда - выражения. Вместо этого, только приложения и комбинаторов S , K и I используются. В этой задаче ваша задача состоит в том, чтобы перевести термины SKI в лямбда-термины в β нормальной форме .
Входная спецификация
Вводом является термин SKI в следующем текстовом представлении. Вы можете выбрать дополнительный трейлинг-перевод строки. Ввода состоит из символов S
, K
, I
, (
, и )
и удовлетворяет следующей грамматикой (в виде ABNF) с sterm
являясь начальным символом:
sterm = sterm combinator ; application
sterm = combinator ;
sterm = '(' sterm ')' ; grouping
combinator = 'S' | 'K' | 'I' ; primitives
Спецификация выхода
Вывод является лямбда-термом без свободных переменных в следующем текстовом представлении. Вы можете выбрать дополнительный трейлинг-перевод строки. Выходные данные должны соответствовать следующей грамматике в форме ABNF, lterm
являющейся начальным символом:
lterm = lterm operand ; application
lterm = ALPHA '.' lterm ; lambda
lterm = operand
operand = '(' lterm ')' ; grouping
operand = ALPHA ; variable (a letter)
Ограничения
Вы можете предположить, что вход имеет нормальную форму β. Вы можете предположить, что в нормальной форме используется не более 26 различных переменных. Вы можете предположить, что и вход, и выход представлены в 79 символах.
Образцы входов
Вот пара примеров входных данных. Выход является одним из возможных выходов для данного входа.
input output
I a.a
SKK a.a
KSK a.b.c.ac(bc)
SII a.aa
счет
Самое короткое решение в октетах выигрывает. Общие лазейки запрещены.
sterm
иlterm
использовать левую ассоциативность, когда скобки отсутствуют.SKI
какS(KI)
.Ответы:
Haskell , 232 байта
Попробуйте онлайн!
Как это работает
Это другой интерфейс синтаксического анализатора моего ответа на «Напишите интерпретатор для нетипизированного лямбда-исчисления» , который также имеет версию без документации с документацией.
Вкратце,
Term = T (Char -> String)
это тип терминов лямбда-исчисления, которые знают, как применять себя к другим терминам (a :: Term -> Term -> Term
) и как отображать себя какString
((%) :: Term -> Char -> String
), учитывая начальную свежую переменную какChar
. Мы можем преобразовать функцию по терминам в термин с помощьюl :: (Term -> Term) -> Term
, и поскольку применение полученного термина просто вызывает функцию (a (l f) == f
), термины автоматически отображаются в обычной форме при отображении.источник
Рубин, 323 байта
Я не могу поверить, что этот кусок дерьма работает вообще:
Использование подстановки регулярных выражений для выполнения β-редукции необработанных строк - это кое-что для Тони-Пони. Тем не менее, его вывод выглядит правильным, по крайней мере, для простых тестовых случаев:
Вот что происходит
K(K(K(KK)))
с некоторой отладочной информацией, которая на моем ноутбуке занимает около 7 секунд, потому что рекурсия регулярного выражения медленная . Вы можете увидеть его α-преобразование в действии!источник
Питон 2, 674
Примечание: после
while 1:
3 строки начинаются с символа табуляции.Это в основном код http://ski.aditsu.net/ , переведенный на python, сильно упрощенный и с большим упором на гольф.
Справка: (это, вероятно, менее полезно сейчас, когда код сжат)
V = переменный член
A = прикладной термин
L = лямбда-член
c = переменный счетчик
p = заменить переменную на член
r = уменьшить
m = окончательное перенумерация переменных
u = внутренняя перенумерация переменных (для дублированных терминов)
s = преобразование строки
(параметр s = self)
C = символ (ы) разделителя для преобразования строк
I, K, S: комбинаторы
E = анализ
Примеры:
(это expected ожидается, потому что
SII(SII)
неприводимо)Спасибо Mauris и Sp3000 за помощь, чтобы убить кучу байтов :)
источник
def m(a,b,c):return foo
вm=lambda a,b,c:foo
даже внутри классов, которые могли бы сэкономить много байт.a.b.c.a(c)(b(c))
как правильное лямбда-выражение: что такое(c)
?Common Lisp, 560 байт
«Наконец-то я нашел применение
PROGV
».Ungolfed
Бета-восстановительная
Переменные динамически связываются во время приведения
PROGV
к новым символам Common Lisp, используяMAKE-SYMBOL
. Это позволяет избежать коллизий именования (например, нежелательное дублирование связанных переменных). Я мог бы использоватьGENSYM
, но мы хотим иметь удобные имена для символов. Вот почему символы названы буквами от aдо z(как разрешено в вопросе).N
представляет код символа следующей доступной буквы в текущей области и начинается с 97, иначе a.Вот более читаемая версия
R
(безW
макроса):Промежуточные результаты
Разбор из строки:
Сокращение:
(См. След исполнения)
Довольно-печати:
тесты
Я повторно использую тот же набор тестов, что и ответ Python:
Восьмой тестовый пример слишком велик для приведенной выше таблицы:
a.a.a.a.a.b.a
является правильным и не использует столько же буквы , как ответ на Python, где привязки кa
,b
,c
иd
не ссылаются.Спектакль
Цикл 7 проходящих тестов выше и сбор результатов немедленно (вывод SBCL):
Выполнение одного и того же теста сто раз приводит к ... «Поток локального хранилища исчерпан» в SBCL из-за известного ограничения, касающегося специальных переменных. При использовании CCL вызов одного и того же набора тестов 10000 раз занимает 3,33 секунды.
источник