clojure - 项目euler primes超时

时间:2015-02-05 23:04:39

标签: clojure

我正在尝试解决项目欧拉问题,要求您提供第n个素数,例如第6个素数是13。

我的代码如下所示:

(ns scratch.core
  (require [clojure.string :as str :only (split-lines join)]))

(def t "2\n3\n6")

(defn work [input]
  (let [lines (map read-string (str/split-lines input))]
    (letfn [(is-prime? [n]
              (or
               (= n 2)
               (empty? (filter #(= 0 (mod n %)) (range 2 (inc (Math/sqrt n)))))))
            (parse-primes [[x & xs]]
              (prn (last (take x (filter #(is-prime? %) (iterate inc 2)))))
              (if (seq xs)
                (recur xs)))]
       (parse-primes (rest lines)))))

(work t)

(def t 2\n3\n6)只是我的测试数据,虽然最大值是10 ^ 4,但我不知道验证答案的程序的实际数字是多少。

我对这段代码感到惊讶,有人可以提出潜在的瓶颈吗?

1 个答案:

答案 0 :(得分:0)

首先,您有理由在最后执行(parse-primes (rest lines))而不是(parse-primes lines)吗?当您的输入String仅包含1个值时会产生异常,例如"6"

然后,正如@ntalbs建议你应该在每个职能中分离一些关注点。保持算法的思路,你可以让parse-primes生成无限的素数序列而不是打印并在输入上重复出现:

(parse-primes []
              (filter #(is-prime? %) (iterate inc 2))) 

然后添加一个特定的函数来获得Nth prime:

(nth-prime [n]
           (nth (parse-primes) n))

然后,您可以将work函数(parse-primes lines)的主要部分替换为(map nth-prime lines),这会使此函数返回序列而不是作为副作用打印并返回nil

作为清理问题,您可以删除work的输入解析以匹配现在返回的序列:

(defn work [rank-of-primes]
  (letfn [...]
    (map nth-prime rank-of-primes)))

(let [ranks-of-primes (map read-string (str/split-lines input))]
  (work ranks-of-primes))

现在只是为了提高性能,您只能测试2中的奇数和is-prime?数字,并使用not-any?进行简化。

(is-prime? [n]
           (not-any? #(= 0 (mod n %)) 
                     (cons 2 (range 3 (inc (Math/sqrt n)) 2)))

此时,如果不修改你选择的算法,它应该更清洁一点:

(defn work [rank-of-primes]
  (letfn [(is-prime? [n]
                     (not-any? #(= 0 (mod n %)) 
                               (cons 2 (range 3 (inc (Math/sqrt n)) 2))))
          (parse-primes []
                        (cons 2 (filter #(is-prime? %) 
                                (cons 2 (iterate (partial + 2) 3)))))
          (nth-prime [n]
                     (nth (parse-primes) n))]
    (map nth-prime rank-of-primes)))

(let [input "2\n3\n6\n10000"
      ranks-of-primes (map read-string (str/split-lines input))]
  (work ranks-of-primes))

在素数问题上有很多值得探讨的问题。如果您对Clojure中的素数算法感兴趣,那么来自C.Grand的blog post更多参与其中。