lisp 函数(普通 lisp 中的计数)
lisp functions ( count numbers in common lisp)
我正在研究与 C 和 lisp 中处理偶数的差异相关的程序,完成了我的 c 程序,但仍然遇到 lisp 的问题
isprime
函数已定义,我需要帮助:
- 定义函数
primesinlist
returns 列表中的唯一素数
这是我到目前为止得到的,
有什么帮助吗?
(defun comprimento (lista)
(if (null lista)
0
(1+ (comprimento (rest lista)))))
(defun primesinlist (number-list)
(let ((result ()))
(dolist (number number-list)
(when (isprime number)
( number result)))
(nreverse result)))
您需要在处理之前 flatten
参数:
(defun primesinlist (number-list)
(let ((result ()))
(dolist (number (flatten number-list))
(when (isprime number)
(push number result)))
(delete-duplicates (nreverse result))))
或者,如果您想避免使用 fresh 列表,请边走边将其展平:
(defun primesinlist (number-list)
(let ((result ()))
(labels ((f (l)
(dolist (x l)
(etypecase x
(integer (when (isprime x)
(push x result)))
(list (f x))))))
(f number-list))
(delete-duplicates (nreverse result))))
要计算不同的素数,取 primesinlist
返回的列表的 length
。
或者,您可以使用 count-if
:
(count-if #'isprime (delete-duplicates (flatten number-list)))
听起来您已经实现了素数测试,但为了完整起见,让我们添加一个非常简单的测试,它只是尝试将一个数除以小于它的数直到它的平方根:
(defun primep (x)
"Very simple implementation of a primality test. Checks
for each n above 1 and below (sqrt x) whether n divides x.
Example:
(mapcar 'primep '(2 3 4 5 6 7 8 9 10 11 12 13))
;=> (T T NIL T NIL T NIL NIL NIL T NIL T)
"
(do ((sqrt-x (sqrt x))
(i 2 (1+ i)))
((> i sqrt-x) t)
(when (zerop (mod x i))
(return nil))))
现在,您需要一种方法将可能嵌套的列表列表展平为单个列表。在处理这个问题时,我通常发现根据由 cons-cells 构建的 trees 来思考会更容易一些。这是一个高效的扁平化函数,returns 一个全新的列表。也就是说,它不与原始树共享任何结构。这很有用,特别是如果我们想稍后修改结果结构,而不修改原始输入。
(defun flatten-tree (x &optional (tail '()))
"Efficiently flatten a tree of cons cells into
a list of all the non-NIL leafs of the tree. A completely
fresh list is returned.
Examples:
(flatten-tree nil) ;=> ()
(flatten-tree 1) ;=> (1)
(flatten-tree '(1 (2 (3)) (4) 5)) ;=> (1 2 3 4 5)
(flatten-tree '(1 () () 5)) ;=> (1 5)
"
(cond
((null x) tail)
((atom x) (list* x tail))
((consp x) (flatten-tree (car x)
(flatten-tree (cdr x) tail)))))
现在只需将列表展平,删除非素数,并从该列表中删除重复项即可。 Common Lisp 包含做这些事情的函数,即 remove-if-not 和 remove-duplicates。这些是不修改其输入参数的 "safe" 版本。因为我们知道扁平化列表是新生成的,所以我们可以使用它们的(潜在的)破坏性对应物,delete-if-not 和 delete-duplicates .
不过,在删除重复元素时需要注意一点。如果您有一个像 (1 3 5 3) 这样的列表,则可以返回两种可能的结果(假设您按顺序排列所有其他元素):( 1 3 5) 和 (1 5 3)。也就是说,您可以删除较晚的重复项或较早的重复项。一般来说,你有 "which one should be left behind?" Common Lisp 的问题,默认情况下,删除 earlier 重复项并保留最后一次出现。该行为可以通过 :from-end 关键字参数进行自定义。在您自己的 API 中复制该行为可能会很好。
所以,这是一个将所有这些考虑因素放在一起的函数。
(defun primes-in-tree (tree &key from-end)
"Flatten the tree, remove elements which are not prime numbers,
using FROM-END to determine whether earlier or later occurrences
are kept in the list.
Examples:
(primes-in-list '(2 (7 4) ((3 3) 5) 6 7))
;;=> (2 3 5 7)
(primes-in-list '(2 (7 4) ((3 3) 5) 6 7) :from-end t)
;;=> (2 7 3 5)"
;; Because FLATTEN-TREE returns a fresh list, it's OK
;; to use the destructive functions DELETE-IF-NOT and
;; DELETE-DUPLICATES.
(delete-duplicates
(delete-if-not 'primep (flatten-tree list))
:from-end from-end))
我正在研究与 C 和 lisp 中处理偶数的差异相关的程序,完成了我的 c 程序,但仍然遇到 lisp 的问题
isprime
函数已定义,我需要帮助:
- 定义函数
primesinlist
returns 列表中的唯一素数
这是我到目前为止得到的, 有什么帮助吗?
(defun comprimento (lista)
(if (null lista)
0
(1+ (comprimento (rest lista)))))
(defun primesinlist (number-list)
(let ((result ()))
(dolist (number number-list)
(when (isprime number)
( number result)))
(nreverse result)))
您需要在处理之前 flatten
参数:
(defun primesinlist (number-list)
(let ((result ()))
(dolist (number (flatten number-list))
(when (isprime number)
(push number result)))
(delete-duplicates (nreverse result))))
或者,如果您想避免使用 fresh 列表,请边走边将其展平:
(defun primesinlist (number-list)
(let ((result ()))
(labels ((f (l)
(dolist (x l)
(etypecase x
(integer (when (isprime x)
(push x result)))
(list (f x))))))
(f number-list))
(delete-duplicates (nreverse result))))
要计算不同的素数,取 primesinlist
返回的列表的 length
。
或者,您可以使用 count-if
:
(count-if #'isprime (delete-duplicates (flatten number-list)))
听起来您已经实现了素数测试,但为了完整起见,让我们添加一个非常简单的测试,它只是尝试将一个数除以小于它的数直到它的平方根:
(defun primep (x)
"Very simple implementation of a primality test. Checks
for each n above 1 and below (sqrt x) whether n divides x.
Example:
(mapcar 'primep '(2 3 4 5 6 7 8 9 10 11 12 13))
;=> (T T NIL T NIL T NIL NIL NIL T NIL T)
"
(do ((sqrt-x (sqrt x))
(i 2 (1+ i)))
((> i sqrt-x) t)
(when (zerop (mod x i))
(return nil))))
现在,您需要一种方法将可能嵌套的列表列表展平为单个列表。在处理这个问题时,我通常发现根据由 cons-cells 构建的 trees 来思考会更容易一些。这是一个高效的扁平化函数,returns 一个全新的列表。也就是说,它不与原始树共享任何结构。这很有用,特别是如果我们想稍后修改结果结构,而不修改原始输入。
(defun flatten-tree (x &optional (tail '()))
"Efficiently flatten a tree of cons cells into
a list of all the non-NIL leafs of the tree. A completely
fresh list is returned.
Examples:
(flatten-tree nil) ;=> ()
(flatten-tree 1) ;=> (1)
(flatten-tree '(1 (2 (3)) (4) 5)) ;=> (1 2 3 4 5)
(flatten-tree '(1 () () 5)) ;=> (1 5)
"
(cond
((null x) tail)
((atom x) (list* x tail))
((consp x) (flatten-tree (car x)
(flatten-tree (cdr x) tail)))))
现在只需将列表展平,删除非素数,并从该列表中删除重复项即可。 Common Lisp 包含做这些事情的函数,即 remove-if-not 和 remove-duplicates。这些是不修改其输入参数的 "safe" 版本。因为我们知道扁平化列表是新生成的,所以我们可以使用它们的(潜在的)破坏性对应物,delete-if-not 和 delete-duplicates .
不过,在删除重复元素时需要注意一点。如果您有一个像 (1 3 5 3) 这样的列表,则可以返回两种可能的结果(假设您按顺序排列所有其他元素):( 1 3 5) 和 (1 5 3)。也就是说,您可以删除较晚的重复项或较早的重复项。一般来说,你有 "which one should be left behind?" Common Lisp 的问题,默认情况下,删除 earlier 重复项并保留最后一次出现。该行为可以通过 :from-end 关键字参数进行自定义。在您自己的 API 中复制该行为可能会很好。
所以,这是一个将所有这些考虑因素放在一起的函数。
(defun primes-in-tree (tree &key from-end)
"Flatten the tree, remove elements which are not prime numbers,
using FROM-END to determine whether earlier or later occurrences
are kept in the list.
Examples:
(primes-in-list '(2 (7 4) ((3 3) 5) 6 7))
;;=> (2 3 5 7)
(primes-in-list '(2 (7 4) ((3 3) 5) 6 7) :from-end t)
;;=> (2 7 3 5)"
;; Because FLATTEN-TREE returns a fresh list, it's OK
;; to use the destructive functions DELETE-IF-NOT and
;; DELETE-DUPLICATES.
(delete-duplicates
(delete-if-not 'primep (flatten-tree list))
:from-end from-end))