Clojure需要合理的逻辑和

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否则返回.

  • 你得到一个序列''(0)`,因为一旦谓词返回非真值,`take-while`就会停止消耗.它将返回0表示为0(偶数且小于100),但对于1则返回false,因为它不均匀.所以你可能想要使用`filter`代替. (2认同)

Art*_*ldt 6

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因为一旦条件为真,这将立即停止,只留下数字零.相反,我们希望使用其中一个谓词作为限制而另一个作为过滤器.

  • 那是因为`(甚至?(部分> 4000000))`返回`(部分> 4000000)` - 它不是*在任何意义上组成两个谓词,而是计算`even?`的逻辑"和" `(部分> 4000000)`.这些既不是'假'也不是'nil`,所以它们都是真的,所以它们中的最后一个将被退回.最终只有`(部分> 4000000)`最终被`take-while`使用. (5认同)