Как переделать код решенной задачи методом рекурсии на реализацию с циклами Do, и Loop - Lisp
Формулировка задачи:
Дана последовательность чисел а1 ... аn. Если в результате замены отрицательных членов последовательности их квадратами, члены будут образовывать последовательность которая уменьшается, то получить сумму членов исходной последовательности, в противном случае получить их произведение.
(DEFUN UBV(L &OPTIONAL (B NIL))
(COND
((NULL L) (SETQ B NIL))
((NULL(CADR L)) B)
((>(CAR L)(CADR L)) (UBV(CDR L)(SETQ B T)))
(T NIL)
))
(DEFUN SUM (L &OPTIONAL (S 0))
(COND
((NULL L) S)
((NOT (NULL L)) (SUM (CDR L) (+ S (CAR L))))
))
(DEFUN MUL (L &OPTIONAL (M 1))
(COND
((NULL L) M)
((NOT (NULL L)) (MUL (CDR L) (* M (CAR L))))
))
(DEFUN PR1(L &OPTIONAL (L2 NIL))
(COND
((AND (NULL L)(NULL L2)) NIL)
((AND (NOT(NULL L))(MINUSP (CAR L))) (PR1 (CDR L) (APPEND L2 (LIST(* (CAR L)(CAR L))))))
((AND (NOT (NULL L))(PLUSP (CAR L))) (PR1 (CDR L) (APPEND L2 (LIST (CAR L)))))
((AND (NULL L) (NOT (NULL L2)) (UBV L2)) (SUM L2))
((AND (NULL L) (NOT (NULL L2)) (NOT (UBV L2))) (MUL L2))
))Решение задачи: «Как переделать код решенной задачи методом рекурсии на реализацию с циклами Do, и Loop»
textual
Листинг программы
;; Функциональное (defun task (lst) (let ((lst-n (mapcar (lambda (x) (if (minusp x) (* x x) x)) lst))) (if (apply '> lst-n) (apply '+ lst) (apply '* lst)))) ==> TASK (task '(100 -8 50 -7)) ==> 135 (task '(1 2 3 4 -1 -2 -3)) ==> -144 ;; итерационное с DO (defun task (lst) (let ((n (length lst)) (r nil)) (do ((i 0 (+ i 1))) ((= i n) (if (apply '< r) (apply '+ lst) (apply '* lst))) (let ((c (nth i lst))) (push (if (minusp c) (* c c) c) r))))) ==> TASK (task '(1 2 3 4 -1 -2 -3)) ==> -144 (task '(100 -8 50 -7)) ==> 135 ;; Итерационное с LOOP (defun task (lst) (let ((n (length lst)) (r nil) (i 0) (c 0)) (loop (when (= i n) (return (if (apply '< r) (apply '+ lst) (apply '* lst)))) (setq c (nth i lst)) (push (if (minusp c) (* c c) c) r) (setq i (+ i 1))))) ==> TASK (task '(100 -8 50 -7)) ==> 135 (task '(1 2 3 4 -1 -2 -3)) ==> -144
Объяснение кода листинга программы
Код выполняет следующие действия:
- Функция
taskпринимает списокlstв качестве входного параметра. - В функциональном варианте кода, список
lstпреобразуется в списокlst-n, где каждый элементxзаменяется на(* x x)еслиxотрицательный, иначе наx. - Затем проверяется, больше ли
lst-nчем текущий элемент спискаlst. Если это так, то выполняется операция сложения для всех элементов спискаlst, иначе выполняется операция умножения. - В итерационном варианте кода с использованием
DO, создается переменнаяr, которая инициализируется как пустой список. - Затем выполняется цикл
DO, который проходит через каждый элемент спискаlst. - Внутри цикла, элемент
cсохраняется в переменнойc. - Если
cотрицательный, то он заменяется на(* c c), иначе наc. - Затем
cдобавляется в списокr. - После завершения цикла, проверяется, равен ли размер списка
rразмеру спискаlst. Если это так, то выполняется операция сложения для всех элементов спискаlst, иначе выполняется операция умножения. - В итерационном варианте кода с использованием
LOOP, создаются переменныеn,r,iиc, которые инициализируются как пустой список и 0 соответственно. - Затем выполняется цикл
LOOP, который проходит через каждый элемент спискаlst. - Внутри цикла, проверяется, равен ли
iразмеру спискаlst. Если это так, то цикл завершается и возвращается результат операцииr. - После проверки условия цикла, элемент
cсохраняется в переменнойc. - Затем
cдобавляется в списокr. - После этого,
iувеличивается на 1. - Если цикл завершается, то выполняется операция сложения для всех элементов списка
lst, иначе выполняется операция умножения.