我遇到了一个问题,即如何编写一个clojure函数来得到方程u + v + x + y + z = 100的一个解,所有变量都是正整数。 这个功能是这样的,如果我们运行(有趣的是100),那么我们得到一个解决方案(例如[1 10 49 3 37]),如果我们再次运行(有趣的是100),我们得到了另一种解决方案(也许[29 46 7] 12 6])
答案 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"
但代码看起来有点复杂,有人能向我们展示更简洁的解决方案吗?