如何在Clojure中得到方程u + v + x + y + z = 100的一个解

时间:2017-02-14 06:58:50

标签: clojure

我遇到了一个问题,即如何编写一个clojure函数来得到方程u + v + x + y + z = 100的一个解,所有变量都是正整数。 这个功能是这样的,如果我们运行(有趣的是100),那么我们得到一个解决方案(例如[1 10 49 3 37]),如果我们再次运行(有趣的是100),我们得到了另一种解决方案(也许[29 46 7] 12 6])

3 个答案:

答案 0 :(得分:4)

Josh的回答提到了一种智能算法,它不会浪费时间来强制执行死胡同。通过跟踪未完成的总和并且仅选择不大于剩余的数字,该算法编写起来非常简单。

(defn sums-to [n total]
  (case n
    1 [[total]]
    (for [i (range (inc total))
          solution (sums-to (dec n) (- total i))]
      (cons i solution))))

它得到了与蛮力方法相同的答案,而不是十分钟,它需要十秒钟才能找到它们:

user> (time (count (sums-to 5 100)))
"Elapsed time: 12734.779787 msecs"
4598126

答案 1 :(得分:2)

这可以通过for列表理解来实现。鉴于您有五个变量,必须执行10B操作,而且需要一点时间(至少在核心i7机器上几分钟。最好的办法是寻找一个智能算法,它会说例如,当x是98,y是1,z是1时,那么通过u和v循环没有用,因为它们必须为零。但是,这是蛮力方法:< / p>

(def solns (for [x (range 101)
                 y (range 101)
                 z (range 101)
                 u (range 101)
                 v (range 101)
                 :when (= 100 (+ x y z u v))]
             [x y z u v]))

现在,您有一个所有解决方案的惰性列表。要小心这一点,因为执行(count solns)(rand-nth solns)(在现代机器上花费大约10分钟)计算量非常大,因为整个列表都将实现。实现列表后,您可以轻松获得(rand-nth solns)的真正随机解决方案,因为计算已经完成。有4,598,126个解决方案。

答案 2 :(得分:0)

最后我自己得到了答案:

(defn fun [total-sum]
  (let [init-part-list (repeat 4 1)
        sum (atom (- total-sum (apply + init-part-list)))
        part-list (map #(let [r (rand-int @sum)]
                           (reset! sum (- @sum r))
                           (+ % r))
                       init-part-list)]
    (cons (- total-sum (apply + part-list)) part-list)))

它确实有效,并且获得结果的时间不到1毫秒

=> (time (fun 100))
"Elapsed time: 0.070562 msecs"

但代码看起来有点复杂,有人能向我们展示更简洁的解决方案吗?