将Clojure解决方案推广到Euler#1

时间:2015-03-05 05:43:34

标签: clojure functional-programming

Q =求出低于1000的所有3或5的倍数之和。

最简单的答案

(reduce + (filter #(or (== (mod % 3) 0) (== (mod % 5) 0)) (range 1000))) 

尝试下面的通用答案

(reduce + (list-nums-divisible-by-all-divisors N div1 div2 ...))
(defn list-nums-divisible-by-all-divisors
    [num & divisors]
    (let [myfn (create-fn divisors)]
        (filter myfn (range num)))) 

这是2个除数的create-fn

(defn create-fn
  [div1 div2]
  #(or (== (mod % div1) 0) (== (mod % div2) 0)))

如何为可变数量的除数编写create-fn?

这是解决这个问题的正确方法吗?我有一种感觉,我应该使用 - >或 - >>操作员,而不是这种方式。

另外,我认为这成为一般性问题。可以使用可变数量的参数创建和返回函数,然后可以将其用作匿名函数(使用其他级别的参数)吗?

提前致谢: - )

1 个答案:

答案 0 :(得分:2)

我建议更细化,构建多个谓词,然后使用every-pred组合它们。这个函数可以非常方便地构建一个谓词。

首先,从一个curried的可分性函数开始:

(defn divisible-by? [n]
  (fn [x]
    (zero? (rem x n))))

Currying只是意味着为了有一个函数"取两个参数",我们首先接受一个参数,然后构建一个接受第二个参数的函数。这些用作

((divisible-by? 3) 6) ;;-> true

在这种情况下,我们需要这种行为,因为我们想要map一个创建一元谓词的函数,如下所示:

(defn create-fn [divisors]
  (apply every-pred (map divisible-by? divisors)))