【问题标题】:How do I define a Scheme procedure that takes a set (a list of distinct elements) and generates a list of all subsets of the set?如何定义一个采用集合(不同元素列表)并生成集合所有子集的列表的 Scheme 过程?
【发布时间】:2021-09-17 22:57:09
【问题描述】:

首先,我想澄清一下,我知道我所问的问题有类似的问题,但我有一个非常具体的输出案例,我正在尝试复制。

我正在尝试创建一个 Scheme 过程,它允许我获取一个集合并生成一个列表,该列表显示该集合的所有可能子集。

例如,如果我调用:(subsets '(a b c )),我应该得到:'((a b c) (b c) (a c) (c) (a b) (b) (a) ())(具体按此顺序)

这是我目前所拥有的:

(define (subsets givenList)
  (if (null? givenList)
      (list null)
      (let ((rest (subsets (cdr givenList))))
        (append rest (map (lambda (x)
                            (cons (car givenList) x))
                          rest)))))

我的输出是:(() (c) (b) (b c) (a) (a c) (a b) (a b c)) 但这不是我正在寻找的特定输出。 有什么建议吗?

【问题讨论】:

  • 所需订单的逻辑是什么?
  • this answer
  • @Barmar 顺序似乎是:所有包含c 的子集在前,然后是包含b 但不是c 的子集,然后是包含a 但不是b 的子集或c。递归地,在c 子集中,包含b 的那些列在仅包含a 的那些之前,并且在那些递归的b 子集中,包含a 的那些列在不包含a 的之前;有一种递归的从右到左的消除规则。

标签: scheme lisp racket


【解决方案1】:

要按所需顺序获取'(a b c) 的所有子集的列表:

  • 首先,作为归纳假设,假设您有一个列表R,其中'(b c) 的所有子集按所需顺序排列,即R = '((b c) (c) (b) ())
  • 然后,将R的每个子列表映射到另一个以元素a开头的子列表,您可以创建列表S = '((a b c) (a c) (a b) (a))
  • 最后可以交错SR的元素,从S的第一个元素开始,得到最终的列表'((a b c) (b c) (a c) (c) (a b) (b) (a) ())
(define (subsets L)
  (if (null? L)
      (list null)
      (let* [(R (subsets (cdr L)))
             (S (map (lambda (x) (cons (car L) x)) R))]
        (interleave S R))))

(define (interleave A B)
  (cond [(null? A) B]
        [(null? B) A]
        [else (cons (car A) (cons (car B) (interleave (cdr A) (cdr B))))]))

例子:

> (subsets '(a b c))
'((a b c) (b c) (a c) (c) (a b) (b) (a) ())

【讨论】:

    猜你喜欢
    • 2021-05-10
    • 2013-08-11
    • 1970-01-01
    • 2017-08-16
    • 2017-01-28
    • 1970-01-01
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多