懒惰的帕斯卡';Clojure中的s三角形
我试图在Clojure中编写一个简洁、懒惰、旋转的行/列,使其沿着三角形的对角线。也就是说,我想生成以下惰性序列:懒惰的帕斯卡';Clojure中的s三角形,clojure,lazy-evaluation,pascals-triangle,Clojure,Lazy Evaluation,Pascals Triangle,我试图在Clojure中编写一个简洁、懒惰、旋转的行/列,使其沿着三角形的对角线。也就是说,我想生成以下惰性序列: ((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)))
((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编程相当陌生,对它所涉及的问题的思考方式也非常不同,因此我非常感谢任何对此有经验的人的建议。简洁而懒惰
(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)
简练懒惰
(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)
pascal不应该是一个var,而是一个生成无限序列的函数 顺便说一句,试试这个:
(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(repeat 1))提供整数溢出异常,但这并不意味着它会生成无限个seq。您可以使用+'来使用大整数。pascal不应该是一个var,而是一个生成无限序列的函数 顺便说一句,试试这个:
(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(repeat 1))提供整数溢出异常,但这并不意味着它会生成无限个seq。你可以使用+'来使用大整数。@A.韦伯的代码更好,他使用的是约化,我不知道。不过你的解释可能对OP更有帮助:)。但我不想使用
seq
作为绑定符号,因为它已经是一个常用的函数了。@a.韦伯的代码更好,他使用了我不知道的缩减。不过你的解释可能对OP更有帮助:)。但是我会避免使用seq
作为绑定符号,因为它已经是一个常用的函数了。你知道为什么第二次调用(取5(n帕斯卡10000))
会给第一次调用不同的结果吗?StackOverFlowError
以某种方式破坏了序列?另外,在我认为您不需要的+
后面有一个'
符号。@OpenSauce确切地说,这演示了惰性seq的第一次调用和缓存结果行为。生成此异常的内容将不再被调用,并且由于该异常已由REPL处理,因此将缓存伪结果。需要时,“+”会自动升级到BigInt
。如果我取的是6而不是5,则会显示+1。你知道为什么第二次调用(取5(n帕斯卡10000))
会给第一次调用不同的结果吗?StackOverFlowError
以某种方式破坏了序列?另外,在我认为您不需要的+
后面有一个'
符号。@OpenSauce确切地说,这演示了惰性seq的第一次调用和缓存结果行为。生成此异常的内容将不再被调用,并且由于该异常已由REPL处理,因此将缓存伪结果。需要时,“+”会自动升级到BigInt
。如果我用6而不是5,这会显示出来。