Skip to content

Instantly share code, notes, and snippets.

@reeFridge
Last active December 11, 2018 09:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reeFridge/22f3717b36cd041140fa3738cc14ac9c to your computer and use it in GitHub Desktop.
Save reeFridge/22f3717b36cd041140fa3738cc14ac9c to your computer and use it in GitHub Desktop.
task 149
;; Напишите функцию (count р х), которая подсчитывает, сколько атомов в списке х удовлетворяет предикату р
;; (р -функция или функциональное имя).
;; Список х не предполагается одноуровневым.
;; кол-во эл-ов
(defun len (l counter)
(if (null l)
counter
(len (cdr l) (+ counter 1))))
;; итоговая реализация
;; добавил print чтобы видеть какие элементы попали в список
;; считает сколько элементов в списке x удовлетворяют предикату (функции) p
(defun countp (p x)
(len (print (filter x p nil)) 0))
;; добавляет head в список l если head проходит проверку предикатом p
(defun add-head-if (head l p)
(if (funcall p head) (cons head l) l))
;; просто функции для удобства чтения с более привычными именами
(defun tail (l) (cdr l))
(defun head (l) (car l))
;; бежим по списку и если очередной элемент явлется атомом
;; и проходит проверку предикатом (предикат возвращает истину с этим элементом)
;; то добавляем его в результирующий список
;; ---
;; если же элемент является не атомом тогда рекурсивно выполняем тоже самое
;; только на уровне этого элемента
;; l - это исходный список, p - функция предикат
;; curr - список в который будут собираться элементы которыйе удовлетворяют предикату p
(defun filter (l p curr)
(if (null l) ;; проверяем пуст ли список l
curr ;; если пуст значит мы просмотрели все элементы и можем вернуть список curr (в котором на этот момент лежат элементы которые прошли проверку)
(filter ;; если же не пуст то рекурсивно вызываем себя же, но уже с другими аргументами:
(tail l) ;; тут вроде понятно (переходим к очередному элементу исходного списка l)
p ;; предикат остается темже
(if (atom (head l)) ;; если текущий рассматриваемы элемент является просто атомом (то есть НЕ списком)
(add-head-if (head l) curr p) ;; то проверяем элемент предикатом p и если он его удовлетворяет, то добавляем этот элемент в curr
(filter (head l) p curr))))) ;; если же это подсписок тогда рассматриваем его таким же образом
;; тестовый предикат: x < 3
(defun less-threep (el) (< el 3))
;; пример вызова
;; (countp 'less-threep '(1 2 3 4 (1 2 3 4 (-5) (-6 8 9 1 -13)) 2 3 -1 -2))
;; >> (-2 -1 2 -13 1 -6 -5 2 1 2 1)
;; >> 11
(print (countp 'less-threep '(1 2 3 4 (1 2 3 4 (-5) (-6 8 9 1 -13)) 2 3 -1 -2)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment