Здравствуйте, дорогие друзья.
Для 8-битной Атари существует единственная версия интерпретатора Лиспа
- Интерлисп/65.
Я заинтересовался Лиспом давно, но всё это было - чисто академический интерес,
так как я вообще не мог представить как его можно использовать на Атари.
Всё же, у меня для сравнения было три версии Интерлиспа и так или иначе, я засел за изучение языка.
Сначала об истории.
В 30-е годы прошлого века жил-был могучий математик Дэвид Гилберт.
После смерти Пуанкаре, его стали считать первым математиком планеты.
Он был вполне непоседлив и изъездил всю математику вдоль и поперёк.
Каждый вздрогнет, вспомнив теорему Коши-Буняковского и Гильбертовы пространства.
Вот с него-то всё и пошло...
Так вот, именно он внезапно перед своими сотрудниками залепил жуткую задачку:
Энтшайдунгс-проблЕм. Задачка эта касалась анализа и формализации вычислимости.
Спросил он следующее: Существует ли формальный аппарат, внутри которого можно
написать произвольное утверждение, которое можно будет доказать за конечное число шагов средствами самого этого аппарата?
Собственно он спросил: "Существуют ли алгоритмы?!!"
Все забегали и озаботились...
Там была ещё парочка шикарных математиков которые вкурили эту проблемку аж на
20-лет и в конце концов оба доказали, что в арифметической формализации - НЕ СУЩЕСТВУЕТ! В общем же случае - Существует.
Благодаря этим исследованиям, один из них с помощью АНАЛИЗА глобальной задачи придумал формализацию "Решающей машины" имени самого себя любимого...
- это был Алан Тюринг и придумал он машину Тюринга.
Второй же, с помощью СИНТЕЗА малых подзадач придумал формальный язык способов вычислений, а именно - теорию "Лямбда исчисления" и это был - Алонзо Чёрч.
В конце концов в 1957 году небезызвестные Джон Бэкус и Петер Наур реализовали язык Фортран,
а небезызвестный Джон Маккарти в 1958 году реализовал язык Лисп.
Разумеется, первый язык был воплощением аналитической тюриговской машины, а второй синтетического Лямбда исчисления.
Сам по себе Наур интересен фамилией, моральный ИНДУС, знаете, ли...
Он Бэкусу сказал, что на Санскрите вообще всё определено, Как, Что и Когда говорить ...
И озаботил Джона !!! И ВОТ Вам факт!
Ну, в общем, я родился в 1959 году и однажды тоже озаботился задачкой вычисления "Счастливого билета" на разных языках.
В случае Фортраноподобных языков, алгоритм будет следующим:
1. Так как на билете шестизнак, то следует построить убывающий цикл,
в котором надо будет делить сам шестизнак, а потом и его остатки на степень десятки (5->0), получая правильные частные значения.
2. Сложить три первых значения, затем три вторых.
Вычесть одну сумму от другой и если 0, то вуаля, вы слопали билет. :)
В случае Лиспоподобных языков, алгоритм выглядит по другому:
1. Распаковать шестизнак в список десятичных чисел.
2. Взять (Счёт ведётся от НУЛЯ) третий хвост списка
3. Найти сумму всех чисел в шестизнаке и вычесть из этой суммы сумму чисел третьего хвоста.
4. При нуле питаться! :)
Вам не показалось, что второй способ - это именно то, как мы-люди интуитивно подсчитываем съедобность билета?
Вот вычислимость билета на ЛИСПЕ:
Код:;;;; Проверка на счастливый билет
;;;; Интерлисп/65 Для Атари 8-бит
;;; Добавим предикат пустоты списка.
(DEFUN NULL (L) ; Зададим имя и параметр функции
(EQ L NIL)) ; Проверка на равенство NIL(Пуст по определению) списка L
;;; Добавим суммирование элементов списка L
(DEFUN SUM (L)
;; NIL это терминатор хвоста любого списка !
;; Используем наш предикат для проверки на исчерпание списка
;; COND проверяет СПИСОК предикатов останавливаясь при первом T !!!
(COND ((NULL L) ; При пустоте или исчерпании списка
0) ; Сумма = 0
(T ; В противном случае, (T - терминатор для COND)
;; рекурсивно, начиная от хвоста прибавляем все частные головы списка ...
;; (CAR L) - предыдущая голова
;; (SUM (CDR L)) - уже найденая сумма хвоста
(+ (CAR L) (SUM (CDR L))))))
;;; Вывод промпта и получение шестизнака
(DEFUN PROMPT NIL
;; PROGN задаёт итеративное исполнение форм
(PROGN (POKE 128 0) ; Отключение промпта Лиспа
(PRIN1 (QUOTE "Enter 6-digits ticket number> ")) ; Печать промпта
(SETQ NUM (READ)))) ; Присвоение переменной данных ввода с клавы
(DEFUN HAPPY-P NUM
(PROGN (SETQ LIS (UNPACK NUM)) ; Присваиваем распакованное число списку
(SETQ S (SUM LIS)) ; Вычисляем полную сумму списка
(SETQ R (SUM (@ LIS 3))) ; Вычисляем сумму элементов 3 хвоста
(SETQ L (SUB S R)))) ; Вычитаем из полной суммы
(DEFUN LUCKY NIL
(COND ((EQ L R) ; Если левая и правая суммы равны
(PROGN (POKE 128 0)
(PRINT (QUOTE "Eat me, Honey !"))))
(T ; В противном случае
(PROGN (POKE 128 0)
(PRINT (QUOTE "Bad-luck poor Yorick !"))))))
(DEFUN TICKET NIL
(PROGN (SETQ NUM 0) ; Инициализация переменных ...
(SETQ LIS NIL) ; ...
(SETQ L 0) ; ...
(SETQ R 0) ; ...
(PROMPT) ; Вывод промпта и ввод шестизнака
(HAPPY-P NUM) ; Проверка на счастливость
(LUCKY))) ; вывод результата

