Fast Prime Number Generation in Clojure

后端 未结 16 1794
萌比男神i
萌比男神i 2020-12-02 12:30

I\'ve been working on solving Project Euler problems in Clojure to get better, and I\'ve already run into prime number generation a couple of times. My problem is that it is

相关标签:
16条回答
  • 2020-12-02 12:53

    Idiomatic, and not too bad

    (def primes
      (cons 1 (lazy-seq
                (filter (fn [i]
                          (not-any? (fn [p] (zero? (rem i p)))
                                    (take-while #(<= % (Math/sqrt i))
                                                (rest primes))))
                        (drop 2 (range))))))
    => #'user/primes
    (first (time (drop 10000 primes)))
    "Elapsed time: 0.023135 msecs"
    => 104729
    
    0 讨论(0)
  • 2020-12-02 12:53

    I just started using Clojure so I don't know if it's good but here is my solution:

    (defn divides? [x i]
      (zero? (mod x i)))
    
    (defn factors [x]
        (flatten (map #(list % (/ x %)) 
                     (filter #(divides? x %) 
                            (range 1 (inc (Math/floor (Math/sqrt x))))))))
    
    (defn prime? [x]
      (empty? (filter #(and divides? (not= x %) (not= 1 %)) 
                     (factors x))))
    
    (def primes 
      (filter prime? (range 2 java.lang.Integer/MAX_VALUE)))
    
    (defn sum-of-primes-below [n]
      (reduce + (take-while #(< % n) primes)))
    
    0 讨论(0)
  • 2020-12-02 12:55

    Here's a simple sieve in Scheme:

    http://telegraphics.com.au/svn/puzzles/trunk/programming-in-scheme/primes-up-to.scm

    Here's a run for primes up to 10,000:

    #;1> (include "primes-up-to.scm")
    ; including primes-up-to.scm ...
    #;2> ,t (primes-up-to 10000)
    0.238s CPU time, 0.062s GC time (major), 180013 mutations, 130/4758 GCs (major/minor)
    (2 3 5 7 11 13...
    
    0 讨论(0)
  • 2020-12-02 12:56

    If you don't need a lazy solution and you just want a sequence of primes below a certain limit, the straight forward implementation of the Sieve of Eratosthenes is pretty fast. Here's my version using transients:

    (defn classic-sieve
      "Returns sequence of primes less than N"
      [n]
      (loop [nums (transient (vec (range n))) i 2]
        (cond
         (> (* i i) n) (remove nil? (nnext (persistent! nums)))
         (nums i) (recur (loop [nums nums j (* i i)]
                           (if (< j n)
                             (recur (assoc! nums j nil) (+ j i))
                             nums))
                         (inc i))
         :else (recur nums (inc i)))))
    
    0 讨论(0)
  • 2020-12-02 12:58
    (defn sieve
      [[p & rst]]
      ;; make sure the stack size is sufficiently large!
      (lazy-seq (cons p (sieve (remove #(= 0 (mod % p)) rst)))))
    
    (def primes (sieve (iterate inc 2)))
    

    with a 10M stack size, I get the 1001th prime in ~ 33 seconds on a 2.1Gz macbook.

    0 讨论(0)
  • 2020-12-02 12:58

    From: http://steloflute.tistory.com/entry/Clojure-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%B5%9C%EC%A0%81%ED%99%94

    Using Java array

    (defmacro loopwhile [init-symbol init whilep step & body]
      `(loop [~init-symbol ~init]
         (when ~whilep ~@body (recur (+ ~init-symbol ~step)))))
    
    (defn primesUnderb [limit]
      (let [p (boolean-array limit true)]
        (loopwhile i 2 (< i (Math/sqrt limit)) 1
                   (when (aget p i)
                     (loopwhile j (* i 2) (< j limit) i (aset p j false))))
        (filter #(aget p %) (range 2 limit))))
    

    Usage and speed:

    user=> (time (def p (primesUnderb 1e6)))
    "Elapsed time: 104.065891 msecs"
    
    0 讨论(0)
提交回复
热议问题