懒惰的帕斯卡';Clojure中的s三角形

懒惰的帕斯卡';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)))

我试图在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)))
               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,这会显示出来。