На этом шаге мы приведем решения некоторых задач с использованием рекурсии.
Структура текста ваших программ для их выполнения с помощью интерпретатора 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).
На следующем шаге мы поговорим о парадигмах программирования.