User Tag List

Показано с 1 по 10 из 27

Тема: Кое-что о Лиспе на Атари-8

Древовидный режим

Предыдущее сообщение Предыдущее сообщение   Следующее сообщение Следующее сообщение
  1. #2

    Регистрация
    26.02.2011
    Адрес
    Москва
    Сообщений
    258
    Спасибо Благодарностей отдано 
    8
    Спасибо Благодарностей получено 
    25
    Поблагодарили
    18 сообщений
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Вообще говоря, история Лиспа - это просто фантасмагория какая-то.
    Ну, не зря говорят, что Лисп - язык Искуственного Интеллекта.

    Дело в том, что когда программируешь на Лиспе, всё время ощущаешь,
    что ГОВОРИШЬ с машиной. Именно на её языке!

    Все начинают обучение Лиспа с Факториала. Для начала и нам он подойдёт.

    Факториал - это произведение всех неотрицательных целых чисел включая заданное.
    Обратите внимание, что НОЛЬ тоже включён, только на него умножать не надо!

    Математически, рекурсивное определение факториала следующее:

    Код:
         /N=0, N! = 1
         \N>0, N! = N * (N-1)!
    А вот - запись на Лиспе:
    Код:
    ;;; Факториал
    (DEFUN ! (N)
      (COND ((EQ N 0) ; При равенстве N нулю
             1)       ; будет единица
    ;; В противном случае N умножается на факториал от (N-1)
            (T (* N (! (SUB N 1))))))
    Как говорится, ищите 10 отличий...

    Вот трассировка:

    Код:
    (! 4)
    
    -->!/ARGS: (4)
     -->!/ARGS: (3)
      -->!/ARGS: (2)
       -->!/ARGS: (1)
        -->!/ARGS: (0)
        <--!/VALUE: 1
       <--!/VALUE: 1
      <--!/VALUE: 2
     <--!/VALUE: 6
    <--!/VALUE: 24
    24
    Стоит заметить, что на каждом этапе рекурсии происходит не только умножение на N, но и вызывается САМ факториал, подразумевающий, в свою очередь ещё одно умножение на N. Из-за того, что ВСЯ функция Факториала вычисляется на каждом этапе рекурсии при помощи ленивых(отложенных) вычислений, всё идёт медленно (Квадратичное замедление!).

    Очевидно, что здесь лучшим был бы рекурсивный подход c накопительным аргументом.

    Пусть наше N будет нумератором. Введём ещё один аргумент A - Аккумулятор, тогда, введя новую функцию !AUX, где счёт рекурсий будет от N до 1, и на каждой будет только умножение N-1 на A, а не рекурсивный вызов Факториала, получим быстрый алгоритм (Линейное замедление).

    Код:
    ;;;Враппер - Вызывающая функция факториала для включения нуля в определение.
    (DEFUN ! (N)
      (COND ((EQ N 0)        ; Если N=0
             1)              ; То !=1
    ;;; При ненулевом аргументе вызов вычисляющей функции с аргументами N и 1.
            (T (!AUX N 1))))
    
    ;;; Быстрая рекурсия факториала. Изначально в Нумераторе - N, в Аккумуляторе - 1.
    (DEFUN !AUX (N A)
      (COND ((EQ N 1) ; Терминатор вычислений. Когда N станет 1,
             A)       ; Выводится накопленное содержимое Аккумулятора.
    ;;; В противном случае функция пошагово декрементирует Нумератор и
    ;;; умножает его на Аккумулятор. Результат помещается в Аккумулятор.
            (T (!AUX (SUB N 1) (* N A)))))
    ;;;              НУМЕРАТОР АККУМУЛЯТОР
    Вот трассировка:

    Код:
    (! 4)
    
    -->!/ARGS: (4)
     -->!AUX/ARGS: (4 1)
      -->!AUX/ARGS: (3 4)
       -->!AUX/ARGS: (2 12)
        -->!AUX/ARGS: (1 24)
        <--!AUX/VALUE: 24
       <--!AUX/VALUE: 24
      <--!AUX/VALUE: 24
     <--!AUX/VALUE: 24
    <--!/VALUE: 24
    24
    Атарька говорит, что (! 40) = 8.159152512E+47
    Без трассировки вычисляет за 1 секунду.

    Чтобы показать мощь языка давайте напишем решение одной задачки, которая не поддалась Алонзо Чёрчу, но была решена его учеником Стивеном Клини через 12 лет.

    Вот математическое рекурсивное определение:

    Код:
    (X=1 + (-1)) = 0
    ((X + 1) + (-1)) = X
    А вот вычислитель на Лиспе:

    Код:
    (DEFUN DCR1 (X Y Z)
      (COND ((EQ X 1) 0) ; По определению, если x=1 То DCR1=0 
            (T           ; При другом X ...
             (COND ((EQ (+ Y 1) X) ; Y - Инкрементный терминатор числа проходов
                    Z)             ; Z - Накопительный аргумент
                   (T    ; В противном случае рекурсия
                    (DCR1 X (+ Y 1) (+ Z 1)))))))
    
    LISP
    (DCR1 5 0 0)
    4
    То есть в своём Декременте мы
    свели вычитание единицы из натурального числа к прибавлению единицы !!!
    Ни одного (SUB N 1) в программе НЕТ!
    Последний раз редактировалось ezswift; 10.12.2020 в 15:00. Причина: Гы, надо поправить ...
    MAC и PC - это всего лишь периферия для Атари...
    130XE|XC12|CA2001|XF551|IDEPlus2.0|SIO2SD|SIO2IDE| RAM576XE+Covoх|SIO2PC|MAXFLASH8|MAXFLASH1|The Ultimate Cartridge|

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Ocean Software кое что...
    от research в разделе Музыка
    Ответов: 55
    Последнее: 01.08.2013, 22:07
  2. Кое-что о микосхемах!
    от Alex_NEMO в разделе Несортированное железо
    Ответов: 9
    Последнее: 13.04.2009, 23:29
  3. Кое-что задаром
    от F0lken в разделе Барахолка (архив)
    Ответов: 0
    Последнее: 15.03.2009, 20:07
  4. кое что из недоделанного..
    от Sayman в разделе Музыка
    Ответов: 2
    Последнее: 09.04.2008, 15:21

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •