我正在尝试在Clojure中编写一个简洁,懒惰的Pascal's Triangle,旋转使得行/列跟随三角形的对角线。也就是说,我想生成以下lazy-seq的lazy-seqs:
((1 1 1 1 ...)
(1 2 3 4 ...)
(1 3 6 10 ...)
...
)
我写的代码是:
(def pascal
(cons (repeat 1)
(lazy-seq
(map #(map + %1 %2)
(map #(cons 0 %) (rest pascal)))
pascal
)))
以便通过将自身的右移版本添加到前一行来形成每一行。问题是它永远不会越过第一行,因为那时(map #(cons 0 %) (rest pascal)))
是空的。
=> (take 5 (map #(take 5 %) pascal))
((1 1 1 1 1))
解决这个问题的合理方法是什么?我对Clojure中的编程很新,并且考虑到它所涉及的问题的方式非常不同,所以我非常感谢任何对此更有经验的人的建议。
答案 0 :(得分:6)
简洁而懒惰
(def pascal (iterate (partial reductions +') (repeat 1)))
(map (partial take 5) (take 5 pascal))
;=> ((1 1 1 1 1)
; (1 2 3 4 5)
; (1 3 6 10 15)
; (1 4 10 20 35)
; (1 5 15 35 70))
但是太懒了?
(take 5 (nth pascal 10000))
;=> StackOverflowError
再试一次
(take 5 (nth pascal 10000))
;=> (0)
呃 - 哦,重新开始,尝试再试一次
(def pascal (iterate (partial reductions +') (repeat 1)))
(count (flatten (map (partial take 5) (take 100000 pascal))))
;=> 500000
现在这些都在你的堆中
(take 5 (nth pascal 100000))
;=> (1 100001 5000150001 166676666850001 4167083347916875001)
答案 1 :(得分:2)
pascal不应该是var,而是一个生成无限seqs的函数。
Check out this question for usage on lazy-seq
顺便说一下,试试这个:(defn gennext [s sum]
(let [newsum (+ (first s) sum)]
(cons newsum
(lazy-seq (gennext (rest s) newsum)))))
(defn pascal [s]
(cons s
(lazy-seq (pascal (gennext s 0)))))
(pascal(重复1))给出整数溢出异常,但这意味着它产生无限的seqs。您可以使用+'来使用大整数。