Shk*_*rik 1 clojure predicates
我正在学习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]))))
Run Code Online (Sandbox Code Playgroud)
Mic*_*zyk 10
要以这种方式组合多个谓词,您可以使用every-pred:
(every-pred even? (partial > 4000000))
Run Code Online (Sandbox Code Playgroud)
此表达式的返回值是一个接受参数的函数,true如果它是偶数且大于4000000则返回,false否则返回.
user> ((partial < 4000000) 1)
false
Run Code Online (Sandbox Code Playgroud)
Partial将静态参数放在第一位,将自由参数放在最后,这样就构建了与你想要的相反的方式.它本质上是生产#(< 4000000 %)而不是#(< % 4000000)你想要的,所以只需>改为<:
user> (reduce +
(take-while (and even? (partial > 4000000))
(map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))))
9227464
Run Code Online (Sandbox Code Playgroud)
或者直接使用匿名函数形式会更清楚:
user> (reduce +
(take-while (and even? #(< % 4000000))
(map first (iterate (fn [[a b]] [b (+ a b)]) [0 1]))))
9227464
Run Code Online (Sandbox Code Playgroud)
现在我们已经介绍了部分内容,让我们分解一个有效的解决方案.我将使用线程最后一个宏->>来分别显示每个步骤.
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
Run Code Online (Sandbox Code Playgroud)
从这里我们可以看出,我们实际上并不想在a上组合谓词 evan?和小于4000000,take-while因为一旦条件为真,这将立即停止,只留下数字零.相反,我们希望使用其中一个谓词作为限制而另一个作为过滤器.