作为某些欧拉苦痛的一部分,我尝试用分解轮编写埃拉托斯提尼筛代码。到目前为止我的代码是:
(defun ring (&rest content)
"Returns a circular list containing the elements in content.
The returned list starts with the first element of content."
(setf (cdr (last content)) content))
(defun factorization-wheel (lst)
"Returns a circular list containing a factorization
wheel using the list of prime numbers in lst"
(let ((circumference (apply #'* lst)))
(loop for i from 1 to circumference
unless (some #'(lambda (x) (zerop (mod i x))) lst)
collect i into wheel
finally (return (apply #'ring
(maplist
#'(lambda (x) ; Takes exception to long lists (?!)
(if (cdr x)
(- (cadr x) (car x))
(- circumference (car x) -1)))
wheel))))))
(defun eratosthenes (n &optional (wheel (ring 4 2)))
"Returns primes up to n calculated using
a Sieve of Eratosthenes and a factorization wheel"
(let* ((candidates (loop with s = 1
for i in wheel
collect (setf s (+ i s))
until (> s n))))
(maplist #'(lambda (x)
(if (> (expt (car x) 2) n)
(return-from eratosthenes candidates))
(delete-if
#'(lambda (y) (zerop (mod y (car x))))
(cdr x)))
candidates)))我得到了以下结果,车轮长度超过6个元素。我真的不明白为什么:
21 > (factorization-wheel '(2 3 5 7 11 13))
(16 2 4 6 2 6 4 2 4 6 6 2 6 4 2 6 4 6 8 4 ...)
21 > (factorization-wheel '(2 3 5 7 11 13 17))
> Error: Too many arguments.
> While executing: FACTORIZATION-WHEEL, in process listener(1).该算法似乎工作正常,否则,并产生素数与车轮有6个或更少的元素。
显然,当长列表传递给apply或ring时,他们会竖起鼻子。
但这个列表不应该算作一个单一的参数吗?我承认我完全迷糊了。如有任何意见,我们将不胜感激。
发布于 2015-12-10 06:06:56
arguments允许实现约束可以传递给函数的最大参数数。这个限制是由呼叫-参数-限制给出的,可以小到50。
对于像代数群算子一样服从联想性质的函数(+、list等),我们可以利用reduce抽取输入列表,同时将其作为二进制函数来实现。
例如,添加一个大的数字列表:(reduce #'+ list)而不是(apply #'+ list)。
关于reduce的注记
在通用Lisp中,即使列表是空的,reduce似乎也能工作。很少有其他语言给您这样的结果,而且它实际上并不来自reduce:它不能适用于所有函数。但是使用+,我们可以编写(reduce #'+ nil),它计算零,就像(apply #'+ nil)一样。
为什么会这样呢?因为可以用零参数调用+函数,当调用零参数时,它会为加法组:0生成标识元素。这与reduce函数相吻合。
在其他一些语言中,必须给fold或reduce函数一个初始的种子值(如0),或者给出一个非空的列表。如果两者都不给,那就是错误。
如果给出一个空列表而没有reduce,则Common :initial-value将调用不带参数的内核函数,并使用返回值作为初始值。由于该值是唯一的值(列表为空),则返回该值。
注意带有最左边参数的特殊规则的函数。例如:
(apply #'- '(1)) -> -1 ;; same as (- 1), unary minus semantics.
(reduce #'- '(1)) -> 1 ;; what?所做的是,当给reduce一个元素列表时,它只是返回元素而不调用函数。
基本上,它建立在上面提到的数学假设之上,如果没有提供:initial-value,那么f将支持(f) -> i,其中i是相对于f的一些恒等元素,因此(f i x) -> x。在还原单例列表(reduce #'f (list x)) -> (f (f) x) -> (f i x) -> x时,它被用作初始值。
-函数不遵守这些规则。(- a 0)的意思是“从a中减去零”,因此产生了a,而(- a)则是a的加性逆,可能是出于纯粹的语用和符号上的原因(也就是说,不让Lisp程序员编写(- 0 a)只是为了让-在reduce和apply下表现得更加一致)。也不能用零参数调用-函数。
如果我们想要获取一个数字列表,并从某个值x中减去它们,模式是:
(reduce #'- list-of-numbers :initial-value x)https://stackoverflow.com/questions/34194355
复制相似问题