[HomeLisp] Сортировка с условием
Формулировка задачи:
(defun vsort (lst)
(cond ((null lst) nil)
(t (let ((max (apply 'max lst)))
(cons max (vsort (removef max lst)))))))
(setq
L
(intersection
'(-1 32 -57 0 -4 -2 41 -41 -5 -7 12 -12 64 128 -256 -14 -42)
'(-1 -12 -2 4 6 8 -4 -256 -57 10 0 41 12)
)
)
(vsort L)Решение задачи: «[HomeLisp] Сортировка с условием»
(DEFUN REMOVE-IF-NOT (P LST &KEY (COUNT NIL) (FROM-END NIL)) (COND (FROM-END (REVERSE (REMOVE-IF-NOT P (REVERSE LST) :COUNT COUNT :FROM-END NIL))) (T (COND ((NULL COUNT) (COND ((NULL LST) NIL) ((NOT (FUNCALL P (CAR LST))) (REMOVE-IF-NOT P (CDR LST))) (T (CONS (CAR LST) (REMOVE-IF-NOT P (CDR LST)))))) (T (COND ((NULL LST) NIL) ((= COUNT 0) LST) ((NOT (FUNCALL P (CAR LST))) (REMOVE-IF-NOT P (CDR LST) :COUNT (SUB1 COUNT))) (T (CONS (CAR LST) (REMOVE-IF-NOT P (CDR LST) :COUNT COUNT)))))))))
Объяснение кода листинга программы
В коде представлена реализация функции REMOVE-IF-NOT, которая принимает три аргумента: P, LST и KEY-BINDING-SYMBOLS.
В первой ветке условия FROM-END является NIL, поэтому выполняется вторая ветка условия T. В ней проверяется, является ли счетчик COUNT равным NIL. Если это так, то выполняется следующая ветка условия, где проверяется, является ли список LST равным NIL. Если это так, то возвращается NIL.
Если COUNT не равен NIL, то выполняется следующая ветка условия. Проверяется, является ли первый элемент списка LST равным NIL. Если это так, то удаляется весь список LST. Если FUNCALL P возвращает NIL, то удаляется весь список LST. Если FUNCALL P возвращает не NIL, то удаляется только этот элемент и возвращается остаток списка.
Если COUNT равен NIL, то возвращается остаток списка LST.
Если COUNT не равен NIL, то выполняется следующая ветка условия. Проверяется, является ли первый элемент списка LST равным NIL. Если это так, то удаляется весь список LST. Если FUNCALL P возвращает NIL, то удаляется весь список LST. Если FUNCALL P возвращает не NIL, то удаляется только этот элемент и возвращается остаток списка.
Если COUNT равен NIL, то возвращается остаток списка LST.
Если COUNT не равен NIL, то выполняется следующая ветка условия. Проверяется, является ли первый элемент списка LST равным NIL. Если это так, то удаляется весь список LST. Если FUNCALL P возвращает NIL, то удаляется весь список LST. Если FUNCALL P возвращает не NIL, то удаляется только этот элемент и возвращается остаток списка.
Если COUNT равен NIL, то возвращается остаток списка LST.