神秘的Clojure功能

问题描述 投票:0回答: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)))

我尝试使用 partitionpartition-all 来验证这些测试,但是我无法得到正确的解决方案。如果你有任何想法如何做到这一点,我真的很感激一点点帮助。我在几个星期前开始使用clojure,但仍然有一些问题。我在几周前开始使用clojure,但仍然存在一些问题。

clojure declarative
1个回答
1
投票

不可能用 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 -startchunk -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))

1
投票

不如这样吧:

(defn floyd []
  (map (fn[n]
         (let [start (/ (* n (inc n)) 2)]
           (range (inc start) (+ start n 2))))
       (iterate inc 0)))

(take 4 (floyd))

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))

这是基于这样的观察而得出的:你想要一系列递增的范围(the (range) 争论 map 是用来产生一个越来越长的范围的序列),每一个序列几乎都是从三角形的数字序列开始的。

(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)))
© www.soinside.com 2019 - 2024. All rights reserved.