生成整数分区-将python代码转换为clojure

生成整数分区-将python代码转换为clojure,clojure,Clojure,我试图为一个数字生成整数分区,但无意中发现了一个似乎非常简洁而优雅的分区: def partitions(n): # base case of recursion: zero is the sum of the empty list if n == 0: yield [] return # modify partitions of n-1 to form partitions of n for p in partitions(n-

我试图为一个数字生成整数分区,但无意中发现了一个似乎非常简洁而优雅的分区:

def partitions(n):
    # base case of recursion: zero is the sum of the empty list
    if n == 0:
        yield []
        return

    # modify partitions of n-1 to form partitions of n
    for p in partitions(n-1):
        yield [1] + p
        if p and (len(p) < 2 or p[1] > p[0]):
            yield [p[0] + 1] + p[1:]
我应该考虑懒惰的序列吗


我很难对python代码进行推理,到目前为止,我转换python代码的尝试都失败了。非常感谢您为我提供的任何帮助。

Tupelo库实现了Python的
yield
函数。以下是翻译:

(ns tst.demo.core
  (:use tupelo.core )

(defn partitions [n]
  (lazy-gen
    (if (zero? n)
      (yield [])
      (doseq [p (partitions (dec n))]
        (yield (glue [1] p))
        (when (and (not-empty? p)
                (or (< (count p) 2)
                  (< (first p) (second p))))
          (yield (prepend (inc (first p))
                   (rest p))))))))

(partitions 4) => 
    ([1 1 1 1] [1 1 2] [2 2] [1 3] [4])
(ns tst.demo.core
(:使用tupelo.core)
(defn分区[n]
(懒将军
(如果(零?n)
(收益率[])
(doseq[p(分区(dec n))]
(屈服强度(胶水[1]p))
(何时(和(不为空?p)
(或(<(计数p)2)
(<(第一个p)(第二个p)))
(收益率(前置(包括第一个p))
(其余p(()()())(())))
(分区4)=>
([1 1 1 1] [1 1 2] [2 2] [1 3] [4])

由于分区的活动端位于前端,因此它最好是一个列表而不是一个向量。这简化了代码的指端

否则,按照你的结构,在Clojure,我们会得到类似于

(defn partitions [n]
  (if (zero? n)
    '(())
    (apply concat
      (for [p (partitions (dec n))]
        (let [res [(cons 1 p)]]
          (if (and (not (empty? p))
                   (or (< (count p) 2) (> (second p) (first p))))
            (conj res (cons (inc (first p)) (rest p)))
            res))))))

你哪里做错了?你没能正确地解开
收益率

  • for
    返回一个或两个分区的向量序列 必须将它们连接成单个序列
  • 您的基本情况也应该返回一系列分区,而不是 一个单独的空分区,算法将其视为 一个空序列,它在递归链中向上传播。 这就是你的结果
还有一些小的改进需要改进,但我放弃了它们,转而更贴近您的代码

(ns tst.demo.core
  (:use tupelo.core )

(defn partitions [n]
  (lazy-gen
    (if (zero? n)
      (yield [])
      (doseq [p (partitions (dec n))]
        (yield (glue [1] p))
        (when (and (not-empty? p)
                (or (< (count p) 2)
                  (< (first p) (second p))))
          (yield (prepend (inc (first p))
                   (rest p))))))))

(partitions 4) => 
    ([1 1 1 1] [1 1 2] [2 2] [1 3] [4])
(defn partitions [n]
  (if (zero? n)
    '(())
    (apply concat
      (for [p (partitions (dec n))]
        (let [res [(cons 1 p)]]
          (if (and (not (empty? p))
                   (or (< (count p) 2) (> (second p) (first p))))
            (conj res (cons (inc (first p)) (rest p)))
            res))))))
=> (partitions 4)
((1 1 1 1) (1 1 2) (2 2) (1 3) (4))