Написать функцию, удаляющую из списка каждый k-ый элемент - Lisp
Формулировка задачи:
В общем есть задачка:
Написать функцию, удаляющую из списка каждый k-ый элемент.
Так вот, написал, прекрасно работает:
И меня интересует вопрос, можно ли ужать этого монстра? А то, как мне кажется можно. Например запихнуть всё в одну функцию? Не используя других стандартных Lisp-функций которые встречаются в коде?
;Главная функция
(defun fun (x k)
(cond
((null x) nil)
(T (append (head x k) (fun (tail x k) k)))
)
)
;Берем все элементы до k-го
(defun head (x k)
(cond
((null x) nil)
((= k 0) nil)
(T (cons (car x) (head (cdr x) (- k 1))))
)
)
;Берем все элементы после k-го
(defun tail (x k)
(cond
((null x) nil)
((> k 0) (tail (cdr x) (- k 1)))
(T (cdr x))
)
)Решение задачи: «Написать функцию, удаляющую из списка каждый k-ый элемент»
textual
Листинг программы
(defun del-every-k (lst k &optional (n 1)) (cond ((null lst) nil) ((= n k) (del-every-k (cdr lst) k 1)) (t (cons (car lst) (del-every-k (cdr lst) k (+ n 1)))))) ==> DEL-EVERY-K (del-every-k '(1 2 3 4 5 6 7 8 9 10) 3) ==> (1 2 4 5 7 8 10) (del-every-k '(1 2 3 4 5 6 7 8 9 10) 2) ==> (1 3 5 7 9) (del-every-k '(1 2 3 4 5 6 7 8 9 10) 1) ==> NIL
Объяснение кода листинга программы
В коде определена функция del-every-k. Она принимает три аргумента: lst — список, из которого следует удалить элементы, k — шаг, с которым следует удалять элементы, и n — номер начального элемента, с которого следует начинать удаление (необязательный аргумент, по умолчанию равный 1).
Функция использует конструкцию cond для проверки трех условий:
- Если
lstравенnil, то возвращаетсяnil, так как удалять элементы из пустого списка не имеет смысла. - Если
nравноk, то функция вызывает саму себя, но уже сcdr lst(т.е. без первого элемента списка),kи1(чтобы начать удаление со следующего элемента после текущего). - Если
nне равноk, то возвращается новый список, состоящий из текущего элемента (car lst), за которым следует результат вызова функции сcdr lst,kиn+1(чтобы продолжить удаление с следующего элемента). Примеры использования функции: —(del-every-k '(1 2 3 4 5 6 7 8 9 10) 3)— удаляет каждый третий элемент из списка, возвращает(1 2 4 5 7 8 10). —(del-every-k '(1 2 3 4 5 6 7 8 9 10) 2)— удаляет каждый второй элемент из списка, возвращает(1 3 5 7 9). —(del-every-k '(1 2 3 4 5 6 7 8 9 10) 1)— удаляет каждый первый элемент из списка, возвращаетnil.