神秘的 Clojure 函数
Mysterious Clojure function
我想编写一个具有以下行为的 clojure 函数:
(take 4 (floyd))
=> '((1) (2 3) (4 5 6) (7 8 9 10))
(take 3 (floyd))
=> '((1) (2 3) (4 5 6))
(take 1 (floyd))
=> '((1)))
我尝试使用 partition
和 partition-all
来验证这些测试,但是我无法获得正确的解决方案。如果您对如何操作有任何想法,我将不胜感激。我几周前开始使用 clojure,但仍然有一些问题。
谢谢
这个怎么样:
(defn floyd []
(map (fn[n]
(let [start (/ (* n (inc n)) 2)]
(range (inc start) (+ start n 2))))
(iterate inc 0)))
(take 4 (floyd))
无法使用 partition
/ partition-all
解决它,因为它们将您的序列分成预定义大小的块。
你可以做的是为此使用递归惰性函数:
user> (defn floyd []
(letfn [(f [n rng]
(cons (take n rng)
(lazy-seq (f (inc n) (drop n rng)))))]
(f 1 (iterate inc 1))))
#'user/floyd
user> (take 1 (floyd))
;;=> ((1))
user> (take 2 (floyd))
;;=> ((1) (2 3))
user> (take 3 (floyd))
;;=> ((1) (2 3) (4 5 6))
user> (take 4 (floyd))
;;=> ((1) (2 3) (4 5 6) (7 8 9 10))
另一个变体可以使用类似的方法,但只跟踪 chunk-start/chunk-size:
user> (defn floyd []
(letfn [(f [n start]
(cons (range start (+ start n))
(lazy-seq (f (inc n) (+ start n)))))]
(f 1 1)))
另一种方法是使用clojure的集合操作函数:
user> (defn floyd-2 []
(->> [1 1]
(iterate (fn [[start n]]
[(+ n start) (inc n)]))
(map (fn [[start n]] (range start (+ start n))))))
#'user/floyd-2
user> (take 4 (floyd-2))
;;=> ((1) (2 3) (4 5 6) (7 8 9 10))
user> (take 5 (floyd-2))
;;=> ((1) (2 3) (4 5 6) (7 8 9 10) (11 12 13 14 15))
user> (take 1 (floyd-2))
;;=> ((1))
还有一个选项:
(defn floyd []
(map (fn [lo n] (range lo (+ lo n 1)))
(reductions + 1 (iterate inc 1))
(range)))
(take 5 (floyd))
;=> ((1) (2 3) (4 5 6) (7 8 9 10) (11 12 13 14 15))
这是基于您想要一系列递增范围的观察得出的(map
的 (range)
参数用于生成一系列越来越长的范围),每个开始来自几乎三角数列:
(take 5 (reductions + 0 (iterate inc 1)))
;=> (0 1 3 6 10)
如果我们从 1
开始该序列,我们会得到您想要的序列中的起始数字:
(take 5 (reductions + 1 (iterate inc 1)))
;=> (1 2 4 7 11)
如果映射函数中的 + 1
困扰您,您可以这样做:
(defn floyd []
(map (fn [lo n] (range lo (+ lo n)))
(reductions + 1 (iterate inc 1))
(iterate inc 1)))
我想编写一个具有以下行为的 clojure 函数:
(take 4 (floyd))
=> '((1) (2 3) (4 5 6) (7 8 9 10))
(take 3 (floyd))
=> '((1) (2 3) (4 5 6))
(take 1 (floyd))
=> '((1)))
我尝试使用 partition
和 partition-all
来验证这些测试,但是我无法获得正确的解决方案。如果您对如何操作有任何想法,我将不胜感激。我几周前开始使用 clojure,但仍然有一些问题。
谢谢
这个怎么样:
(defn floyd []
(map (fn[n]
(let [start (/ (* n (inc n)) 2)]
(range (inc start) (+ start n 2))))
(iterate inc 0)))
(take 4 (floyd))
无法使用 partition
/ partition-all
解决它,因为它们将您的序列分成预定义大小的块。
你可以做的是为此使用递归惰性函数:
user> (defn floyd []
(letfn [(f [n rng]
(cons (take n rng)
(lazy-seq (f (inc n) (drop n rng)))))]
(f 1 (iterate inc 1))))
#'user/floyd
user> (take 1 (floyd))
;;=> ((1))
user> (take 2 (floyd))
;;=> ((1) (2 3))
user> (take 3 (floyd))
;;=> ((1) (2 3) (4 5 6))
user> (take 4 (floyd))
;;=> ((1) (2 3) (4 5 6) (7 8 9 10))
另一个变体可以使用类似的方法,但只跟踪 chunk-start/chunk-size:
user> (defn floyd []
(letfn [(f [n start]
(cons (range start (+ start n))
(lazy-seq (f (inc n) (+ start n)))))]
(f 1 1)))
另一种方法是使用clojure的集合操作函数:
user> (defn floyd-2 []
(->> [1 1]
(iterate (fn [[start n]]
[(+ n start) (inc n)]))
(map (fn [[start n]] (range start (+ start n))))))
#'user/floyd-2
user> (take 4 (floyd-2))
;;=> ((1) (2 3) (4 5 6) (7 8 9 10))
user> (take 5 (floyd-2))
;;=> ((1) (2 3) (4 5 6) (7 8 9 10) (11 12 13 14 15))
user> (take 1 (floyd-2))
;;=> ((1))
还有一个选项:
(defn floyd []
(map (fn [lo n] (range lo (+ lo n 1)))
(reductions + 1 (iterate inc 1))
(range)))
(take 5 (floyd))
;=> ((1) (2 3) (4 5 6) (7 8 9 10) (11 12 13 14 15))
这是基于您想要一系列递增范围的观察得出的(map
的 (range)
参数用于生成一系列越来越长的范围),每个开始来自几乎三角数列:
(take 5 (reductions + 0 (iterate inc 1)))
;=> (0 1 3 6 10)
如果我们从 1
开始该序列,我们会得到您想要的序列中的起始数字:
(take 5 (reductions + 1 (iterate inc 1)))
;=> (1 2 4 7 11)
如果映射函数中的 + 1
困扰您,您可以这样做:
(defn floyd []
(map (fn [lo n] (range lo (+ lo n)))
(reductions + 1 (iterate inc 1))
(iterate inc 1)))