我正在学习Clojure并尝试使用这种语言解决Project的Euler(http://projecteuler.net/)问题。 第二个问题要求找到Fibonacci序列中偶数值的总和,其值不超过四百万。
我已经尝试了几种方法,如果我能找到它破碎的地方,我会发现下一种方法最准确。现在它返回0.我很确定暂停条件存在问题,但无法弄明白。
(reduce +
(take-while (and even? (partial < 4000000))
(map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))))
答案 0 :(得分:10)
要以这种方式撰写多个谓词,您可以使用every-pred
:
(every-pred even? (partial > 4000000))
此表达式的返回值是一个接受参数的函数,如果它是偶数且大于4000000则返回true
,否则返回false
。
答案 1 :(得分: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
现在我们已经介绍了部分内容,让我们分解一个有效的解决方案。我将使用线程最后一个宏->>
分别显示每个步骤。
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?
上撰写谓词 take-while
和小于4000000,因为这会很快停止因为任何条件都是真的,只留下数字零。相反,我们希望使用其中一个谓词作为限制而另一个作为过滤器。