1

I am learning Clojure and trying to solve Project's Euler (http://projecteuler.net/) problems using this language. Second problem asks to find the sum of the even-valued terms in Fibonacci sequence whose values do not exceed four million.

I've tried several approaches and would find next one most accurate if I could find where it's broken. Now it returns 0. I am pretty sure there is a problem with take-while condition but can't figure it out.

(reduce + 
  (take-while (and even? (partial < 4000000))  
    (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))))
4

2 回答 2

10

要以这种方式组合多个谓词,您可以使用every-pred

(every-pred even? (partial > 4000000))

这个表达式的返回值是一个函数,它接受一个参数,true如果它是偶数并且大于 4000000,则返回,false否则返回。

于 2013-12-30T22:57:29.197 回答
6
user> ((partial < 4000000) 1) 
false 

Partial 将静态参数放在最前面,将自由参数放在最后,因此它构建的结​​果与您想要的相反。它本质上是在生产#(< 4000000 %)而不是#(< % 4000000)按照您的预期生产,因此只需将其更改><

user> (reduce +
        (take-while (and even? (partial > 4000000))
                         (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))))
9227464

或者直接使用匿名函数形式可能会更清楚:

user> (reduce +
              (take-while (and even? #(< % 4000000))
                          (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))))
9227464 

现在我们已经介绍了一些关于部分的内容,让我们分解一个可行的解决方案。我将使用 thread-last 宏->>分别显示每个步骤。

user> (->> (iterate (fn [[a b]] [b (+ a b)]) [0 1]) ;; start with the fibs
           (map first)                              ;; keep only the answer   
           (take-while #(< % 4000000))              ;; stop when they get too big
           (filter even?)                           ;; take only the even? ones
           (reduce +))                              ;; sum it all together.
4613732

从这里我们可以看到,我们实际上并不想在 evan?a 上组合谓词和小于 4000000,take-while因为只要任一条件为真,这就会停止,只留下数字零。相反,我们希望将其中一个谓词用作限制,将另一个用作过滤器。

于 2013-12-30T22:41:31.893 回答