以整数分区问题为例,我可以编写以下代码来输出正整数n
的所有分区:
(defn foo
([n] (foo n n []))
([n k buf]
(if (zero? n)
(println buf)
(doseq [i (range 1 (inc (min n k)))]
(foo (- n i) i (conj buf i))))))
然后(foo 5)
输出:
[1 1 1 1 1]
[2 1 1 1]
[2 2 1]
[3 1 1]
[3 2]
[4 1]
[5]
问题是如何编写一个函数bar
来生成包含此类结果的lazy-seq?例如,我希望(bar 5)
生成([1 1 1 1 1] [2 1 1 1] [2 2 1] [3 1 1] [3 2] [4 1] [5])
。
答案 0 :(得分:2)
这是一个大致等效的函数,将分区生成为一系列序列:
(defn bar
([n] (bar n n))
([n k]
(if (zero? n)
[[]]
(for [i (range 1 (inc (min n k))), tail (bar (- n i) i)]
(cons i tail)))))
例如,
(bar 5)
; ((1 1 1 1 1) (2 1 1 1) (2 2 1) (3 1 1) (3 2) (4 1) (5))
bar
有多懒?
for
很懒。lazy-seq
中。 我怀疑上述情况。
n
。lazy-seq
我怀疑只是懒得堆积
序列,在访问时产生与递归调用栈一样深的序列
第一要素。 此外,重复计算相同的tail
s;因为(bar n k)
对所有k >= n
都是一样的,所以更是如此。
如果此功能的性能是特定问题,则存在每步的恒定时间的迭代算法。正如@ CharlesDuffy的评论暗示的那样,可以重新设置这些以产生延迟序列。
为什么当你能看书时凝视水晶球?
标准名称空间clojure.math.combinatorics
,托管here,包含一个partition
函数,可以生成任何对象序列的分区的延迟序列 - 快速。整数分区是我们计算相同对象的每个分区的元素的地方。它们以反向词典顺序出现。
例如
(map #(map count %) (combo/partitions (repeat 5 :whatever)))
;((5) (4 1) (3 2) (3 1 1) (2 2 1) (2 1 1 1) (1 1 1 1 1))
毫无疑问,可以删除代码来处理这种情况。
答案 1 :(得分:1)
这是递归解决方案。有一些方法可以优化它,而代码并不是最好的。
(defn partitions [n]
(loop [m n
res [(init-step n m)]]
(let [l (last res)]
(if (= m 1)
res
(if (last-step? (last res))
(recur (- m 1) (vec (conj res (init-step n (- m 1)))))
(recur m (next-step res)))))))
(defn init-step [n m]
(if (= n m)
[n]
(loop [res [m (- n m)]]
(let [l (last res)
f (first res)]
(if (<= l f)
res
(recur (vec (conj (vec (butlast res)) f (- l f)))))))))
(defn next-step [res]
(let [input-vec (last res)
cnt (count input-vec)
i (.indexOf input-vec 1)
j (if (> i -1) (- i 1) (- cnt 1))
m (- cnt j)
new-vec (conj (vec (take j input-vec)) (- (input-vec j) 1))]
(conj res (vec (concat new-vec (repeat m 1))))))
(defn last-step? [input-vec]
(if
(or (nil? input-vec)
(= (count input-vec) 1)
(= (input-vec 1) 1)) true
false))
(partitions 10)
#=> [[10] [9 1] [8 2] [8 1 1] [7 3] [7 2 1] [7 1 1 1] [6 4] [6 3 1] [6 2 1 1] [6 1 1 1 1] [5 5] [5 4 1] [5 3 1 1] [5 2 1 1 1] [5 1 1 1 1 1] [4 4 2] [4 4 1 1] [4 3 1 1 1] [4 2 1 1 1 1] [4 1 1 1 1 1 1] [3 3 3 1] [3 3 2 1 1] [3 3 1 1 1 1] [3 2 1 1 1 1 1] [3 1 1 1 1 1 1 1] [2 2 2 2 2] [2 2 2 2 1 1] [2 2 2 1 1 1 1] [2 2 1 1 1 1 1 1] [2 1 1 1 1 1 1 1 1] [1 1 1 1 1 1 1 1 1 1]]