Clojure素数懒惰序列

时间:2009-10-19 19:46:13

标签: python clojure

以下Python代码的Clojure等价物(对于精确算法)是什么?

from itertools import count
from math import sqrt

def prime_gen():
   primes = []
   for n in count(2):
       if all(n%p for p in primes if p <= sqrt(n)):
           primes.append(n)
           yield n

3 个答案:

答案 0 :(得分:10)

这就像我能做到的那样:

(def prime-gen
     (let [primes (atom [])]
       (for [n (iterate inc 2)
             :when (not-any? #(zero? (rem n %))
                             (filter #(<= % (Math/sqrt n)) 
                                     @primes))]
         (do (swap! primes conj n)
             n))))

(take 10 prime-gen)  ; => (2 3 5 7 11 13 17 19 23 29)

Clojure不认为整数0是布尔值false。我花了几分钟才发现你的Python代码正在利用这个。

Here是Clojure中的一些其他素数算法。 clojure.contrib.lazy-seqs中还有一个素数实现。

答案 1 :(得分:0)

这个版本比@Brian Carper的快得多

(def prime-gen
  (let [primes (atom [2N])]
    (iterate
      #(let [ps @primes]
         (loop [n (inc %)]
           (if (loop [i 0]
                 (let [p (nth ps i)]
                   (cond
                     (< n (* p p)) true
                     (zero? (mod n p)) false
                     :else (recur (inc i)))))
             (do (swap! primes conj n) n)
             (recur (inc n)))))
      (first @primes))))

答案 2 :(得分:0)

这是相当惯用的Clojure中的算法。我试图保持名称相同,以便您可以看到这段代码的对应方式。

(def all? (partial every? identity))

(defn prime-gen []
  (let [unfold
        (iterate
          (fn step [[primes n]]
            (if (all?
                  (for [p primes :when (<= p (Math/sqrt n))]
                    (not= 0 (mod n p))))
              [(conj primes n) (inc n)]
              (recur [primes (inc n)])))
          [[] 2])]
    (map (comp peek first) (rest unfold))))

step的每次迭代

  • 将下一个质数附加到其参数的第一部分,并且
  • 动手第二部分的下一个候选素数。

最后一行从迭代中选择附加的素数。

有效:

(take 11 (prime-gen))
=> (2 3 5 7 11 13 17 19 23 29 31)

我们还可以看到一些效率低下的问题: :when (<= p (Math/sqrt n)子句(及其等效的Python if p <= sqrt(n))是没有用的。我们仍然要遍历所有发现的primes,而不是在它们变得太大而不能成为可能的因素时停下来。为了弥补这一点,

  • 在Clojure中,我们将:when替换为:while;
  • 在Python中,我认为我们将primes包裹在takewhile中,而不是 紧跟着if(未试用)。

即使如此,该算法也很慢。如需更快的操作,请参见Christophe Grand's blog on the subject中的lazy-primes3