【问题标题】:Generating integer partitions - Converting python code with yield to clojure生成整数分区 - 将带有 yield 的 python 代码转换为 clojure
【发布时间】:2019-01-25 04:46:48
【问题描述】:

我正在尝试为数字生成整数分区,并偶然发现了this,它看起来非常简洁和优雅:

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:]

因此,我尝试将其转换为 Clojure,但失败了:

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

^^ 上面写错了。例如:

eul=> (partitions 4)
()

我应该考虑惰性序列吗?

我在推理 python 代码时遇到了麻烦,到目前为止我尝试转换它的尝试都失败了。感谢任何帮助我弄清楚如何做到这一点。

【问题讨论】:

标签: clojure


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    由于分区的活动端在最前面,所以最好是列表而不是向量。这简化了代码的手指末端。

    否则坚持你的结构,我们在 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))))))
    

    有效:

    => (partitions 4)
    ((1 1 1 1) (1 1 2) (2 2) (1 3) (4))
    

    你哪里做错了?您未能正确解开yields。

    • for 返回一个或两个分区的向量序列。你 必须将它们连接成一个序列。
    • 你的基本情况也应该返回一个分区序列——不是 您尝试做的单个空分区。该算法将其视为 一个空序列,它在递归链上传播自身。 因此你的结果。

    还有一些小的改进需要做,但我放弃了它们以支持更接近您的代码。

    【讨论】:

      猜你喜欢
      • 2014-03-29
      • 2013-07-09
      • 2012-05-01
      • 2017-01-01
      • 2019-10-17
      • 1970-01-01
      • 1970-01-01
      • 2020-09-02
      相关资源
      最近更新 更多