【发布时间】:2016-01-17 16:02:30
【问题描述】:
我写了一个函数is-prime,它验证给定的数字是否是素数,并相应地返回t或nil。
(is-prime 2) ; => T
(is-prime 3) ; => T
(is-prime 4) ; => NIL
到目前为止,一切都很好。现在我想生成min 和max 之间的素数列表,所以我想提出一个函数,将这两个值作为参数并返回所有素数的列表:
(defun get-primes (min max)
...)
现在这是我目前卡住的地方。当然,我可以做的是创建一个列表,其中包含从min 到max 的所有数字范围,并在其上运行remove-if-not。
无论如何,这意味着,我首先必须创建一个潜在的巨大列表,其中包含很多我无论如何都会丢弃的数字。所以我想反过来做,建立一个列表,只包含min 和max 之间的数字,根据is-prime 谓词实际上是素数。
我怎样才能以功能的方式做到这一点,即不使用loop?我目前的方法(使用loop)如下所示:
(defun get-primes (min max)
(loop
for guess from min to max
when (is-prime guess)
collect guess))
也许这是一个完全愚蠢的问题,但我想我没有只见树木不见森林。
有什么提示吗?
【问题讨论】:
-
我想你可以递归地遍历每个数字并检查它。类似(非常粗糙,很久没有在 lisp 中做过任何事情)
(defun primes (start end res) (cond (< start end) (primes (+ start 1) end (if (is-prime start) (cons start res) res) (eq start end) res)) -
您是否期望
get-primes以非常大的min值被调用?如果不是,我会想象使用Sieve of Eratosthenes 将比你的is-prime更有效,并且使用它会使问题变得毫无意义(因为无论如何你都会使用一组真/假位)。跨度> -
@jkiiski 哈哈,感谢您指出这一点:-)!实际上,Eratosthenes 的筛子正是我来自的地方,由于
max值很大,我遇到了内存问题,总是不得不从2开始很烦人确保即使对于非常大的min值,也会消除正确的值。所以基本上,是的,你是对的,但我已经是这样了:-) -
当
min值很大时,为了更小的内存占用,使用两个数组 - 一个从 2 到(sqrt max)的 core 和一个 "offset" 段 从min到max和sieve them at the same time。
标签: functional-programming lisp common-lisp primes