На этом шаге мы приведем решения некоторых задач с использованием рекурсии.
Структура текста ваших программ для их выполнения с помощью интерпретатора muLISP85:
; -------------------------------------------------------- ; Условие вашей задачи ; -------------------------------------------------------- (DEFUN Имя_вашей_функции (LAMBDA (Аргументы_вашей_функции) Тело функции )) (RDS)
Для загрузки ваших функций в интерпретатор muLISP85 используйте функцию RDS следующим образом: (RDS Имя_файла.Расширение_файла).
Демонстрационные примеры
(DEFUN SUMMA (LAMBDA (X Y)
(+ X Y)
))
; ---------------------
(DEFUN ADD1 (LAMBDA (NUM)
; Функция инкремента
(+ NUM 1)
))
; ---------------------
(DEFUN SUB1 (LAMBDA (NUM)
; Функция декремента
(- NUM 1)
))
; ------------------------
(DEFUN PROCENT (LAMBDA (A B)
; Функция возвращает A процентов от числа B
(/ (* A 100) B)
))
; --------------------
(DEFUN ABS (LAMBDA (NUM)
; Функция ABS возвращает абсолютное значение аргумента NUM
(COND ( (MINUSP NUM) (- NUM))
( T NUM )
)
))
; --------------------
(DEFUN MAX (LAMBDA (M N)
; Функция MAX возвращает большее из двух чисел
(COND ( (> M N) M )
( T N )
)
))
; ----------------------
(DEFUN KPLUS (LAMBDA (X Y)
; Фрагмент комплексной арифметики
; X и Y - списки вида (x y)
(LIST (+ (CAR X) (CAR Y))
(+ (CADR X) (CADR Y)) )
))
(DEFUN FACT (LAMBDA (X)
(COND ( (ZEROP X) 1 )
( T (* X (FACT (- X 1))) )
)
))
Изобразим процесс нисходящей рекурсии графически:
(FACT 3)
--------
V
(* 3 (FACT 2))
---------
V
(* 2 (FACT 1))
---------
V
(* 1 (FACT 0))
---------
V
1
А теперь изобразим процесс "выхода из рекурсии":
(* 3 (* 2 (* 1 1))) -> 6
(DEFUN FN (LAMBDA (N)
(COND
( (> N 100) (- N 10) )
( T (FN (FN (FN (+ N 21)))) )
)
))
Тестовые примеры:
$ (FN 94)
91
$ (FN 100)
91
$ (FN 123)
113
(DEFUN COPY (LAMBDA (LST) ; Функция для копирования самого ; "верхнего" уровня списка LST (COND ( (NULL LST) NIL ) ( T (CONS (CAR LST) (COPY (CDR LST))) ) ) ))
(DEFUN DROPLAST (LAMBDA (L)
(COND
( (NULL L) NIL )
( (NULL (CDR L)) NIL )
( T (CONS (CAR L) (DROPLAST (CDR L))) )
)
))
(DEFUN ATOMLIST (LAMBDA (X)
(COND
( (NULL X) T )
( (ATOM X) NIL )
( (ATOM (CAR X)) (ATOMLIST (CDR X)) )
( T NIL )
)
))
(DEFUN DELETEFIRST (LAMBDA (A L)
(COND
( (NULL L) NIL )
( (EQUAL (CAR L) A) (CDR L) )
( T (CONS (CAR L) (DELETEFIRST A (CDR L))) )
)
))
(DEFUN EVERYSECOND (LAMBDA (L)
(COND
( (NULL L) NIL )
( (NULL (CDR L)) L )
( T (CONS (CAR L) (EVERYSECOND (CDDR L))) )
)
))
(DEFUN MAXIM (LAMBDA (LST)
(COND
( (NULL LST) NIL )
( (EQ (LENGTH LST) 1) (CAR LST) )
( T (MAX2 (CAR LST) (MAXIM (CDR LST))) )
)
))
; ---------------------
(DEFUN MAX2 (LAMBDA (X Y)
(COND
( (> X Y) X )
( T Y )
)
))
Какие исправления необходимо сделать в программе, чтобы получить наименьший
элемент?
(DEFUN SP (LAMBDA (LST)
(LIST (SUM LST) (PR LST))
))
; --------------------
(DEFUN SUM (LAMBDA (LST)
; Сумма элементов числового списка
(COND
( (NULL LST) 0 )
( T (+ (CAR LST) (SUM (CDR LST))) )
)
))
; -------------------
(DEFUN PR (LAMBDA (LST)
; Произведение элементов числового списка LST
(COND
( (NULL LST) 1 )
( T (* (CAR LST) (PR (CDR LST))) )
)
))
Тестовые примеры:
$ (SP '(1 2 3 4))
(10 24)
$ (SP '())
(0 1)
$ (SP '(1))
(1 1)
$ (SP '(0 1))
(1 0)
(DEFUN AAA (LAMBDA (LST)
(KOL LST (MAXIM LST))
))
; ----------------------
(DEFUN KOL (LAMBDA (LST M)
(COND
( (NULL LST) 0 )
( (EQ (CAR LST) M) (ADD1 (KOL (CDR LST) M)) )
( T (KOL (CDR LST) M) )
)
))
; ----------------------
(DEFUN MAXIM (LAMBDA (LST)
; Функция возвращает максимальный элемент списка LST
(COND
( (NULL LST) NIL )
( (EQ (LENGTH LST) 1) (CAR LST) )
( T (MAX2 (CAR LST) (MAXIM (CDR LST))) )
)
))
; ---------------------
(DEFUN MAX2 (LAMBDA (X Y)
; Функция возвращает наибольшее из двух чисел X и Y %
( ((> X Y) X ) Y )
))
; ---------------------
(DEFUN ADD1 (LAMBDA (NUM)
; Функция, увеличивающая аргумент на 1
(+ NUM 1)
))
Тестовые примеры:
$ (AAA '(1 2 3 4 5))
1
$ (AAA '(2 2 3 4 5))
2
$ (AAA '(5 5 5 5 5))
5
$ (AAA '())
0
(DEFUN MAIN (LAMBDA (LST)
(POSITION (MAXIM LST) LST)
))
; ----------------------
(DEFUN MAXIM (LAMBDA (LST)
; Функция возвращает наибольший элемент списка
(COND
( (NULL LST) NIL )
( (EQ (LENGTH LST) 1) (CAR LST) )
( T (MAX2 (CAR LST) (MAXIM (CDR LST))) )
)
))
; ---------------------
(DEFUN MAX2 (LAMBDA (X Y)
; Функция возвращает наибольшее из двух чнсел X и Y
(COND
( (> X Y) X )
( T Y )
)
))
; ----------------------------
(DEFUN POSITION (LAMBDA (X LST)
; Функция POSITION возвращает положение атома X в
; одноуровневом списке LST (первый элемент имеет
; номер 1). Если элемента в списке нет, то функция
; возвращает 0.
(COND
( (NULL LST) 0 )
( (EQ X (CAR LST)) 1 )
( (MEMBER X LST)
(+ 1 (POSITION X (CDR LST))) )
( T 0 )
)
))
Тестовые примеры:
$ (MAIN '(6 8 3 5 8 4 2 8))
2
$ (MAIN '(6 1 3 5 8 4 2 8))
5
(DEFUN REMBER (LAMBDA (X LST)
(COND
( (NULL LST) NIL )
( (EQ X (CAR LST)) (REMBER X (CDR LST)) )
( T (CONS (CAR LST) (REMBER X (CDR LST))) )
)
))
Тестовые примеры:
$ (REMBER 5 '(4 6 5 7 2 5 9 5 87))
(4 6 7 2 9 87)
$ (REMBER 12 '(1 86 12 6 7 12 0)
(1 86 6 7 0)
(DEFUN CDNR (LAMBDA (N LST)
(COND
( (EQ N 0) LST )
( (EQ N 1) (CDR LST) )
( T (CDNR (- N 1) (CDR LST)) )
)
))
Тестовые примеры:
$ (CDNR 3 '(1 2 3 4 5))
(4 5)
$ (CDNR 3 '(1 2 (3 4 5)))
NIL
$ (CDNR 3 '(1 2 3 (4 5) 6))
((4 5) 6)
$ (MAIN '(1 2 3) 2 '(4 5 6)) (1 2 4 5 6 3)Решение:
(DEFUN MAIN (LAMBDA (LST1 N LST2)
(COND
( (EQ (LENGTH LST1) N) (APPEND LST1 LST2) )
( T (APPEND (FIRSTN LST1 N) (APPEND LST2
(LASTN LST1 (- (LENGTH LST1) N)))
)
)
)
))
; -------------------------
(DEFUN FIRSTN (LAMBDA (LST N)
; Выделяет в список первые N элементов списка LST
(COND ( (EQ N 1) (LIST (CAR LST)) )
( T (CONS (CAR LST) (FIRSTN (CDR LST)
(- N 1))))
)
))
; ------------------------
(DEFUN LASTN (LAMBDA (LST N)
; Выделяет в список последние N элементов списка LST
(REVERSE (FIRSTN (REVERSE LST) N))
))
; -----------------------------
(DEFUN APPEND (LAMBDA (LST1 LST2)
; Составляет список из первых N элементов списка LST1
; и вставляемого списка LST2
(COND ( (NULL LST1) LST2 )
( T (CONS (CAR LST1)
(APPEND (CDR LST1) LST2) ))
)
))
Задачи для самостоятельного решения
$ (REVERSE2 ((A B) (C D))) (B A D C)
$ (INSLIST (2 (A B) (C D))) (A D C B)
REM (A*A,B/2,C), для A<C,B>2, B-четное;
MOD (A*REM(A*A,(B-1)/2,C)),
REM(A,B,C) = для A<C,B>=3, B-нечетное;
A, для A<C, B=1;
REM (MOD (A,C),B,C), для A>=C.
Написать программу для вычисления REM(A,B,C).
На следующем шаге мы поговорим о парадигмах программирования.