首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在方案中实现powerset

在方案中实现powerset
EN

Stack Overflow用户
提问于 2017-03-18 12:09:57
回答 1查看 2K关注 0票数 3

我正试图通过两种方式在Scheme中实现powerset函数。一种方法是使用尾递归,我是这样做的:

代码语言:javascript
复制
(define (powerset list)
 (if (null? list) '(())                                    ;; if list is empty, its powerset is a list containing the empty list
  (let ((rest (powerset (cdr list))))                   ;; define "rest" as the result of the recursion over the rest of list
    (append (map (lambda (x) (cons (car list) x)) rest) ;; add the first element of list to the every element of rest (which is a sublist of rest) 
            rest))))                                    ;; and append it to rest itself (as we can either use the current element (car list), or not

效果很好。

另一种方法是使用foldr,这是我面临的一些问题。我目前的实现如下:

代码语言:javascript
复制
(define (powerset-fr list)
 (foldr (lambda (element result)        ;; This procedure gets an element (and a result);
       (if (null? result) ;; if starting with the empty list, there is nothing to "fold over".
           (cons '() (cons element result))
           (foldr (lambda (inner-element inner-result)
                    (append (cons element result) inner-result))
                  '(())
                  result)))
     '()                             ;; The result is initialized to the empty list,
     list))                         ;; and the procedure is being applied for every element in the first list (list1)

结果很差。

我将尝试解释一下到目前为止我是如何处理这个问题的:

foldr运行给定集合中的每个元素。对于每个这样的元素,我应该向powerset添加一些新元素。这些应该是哪些元素?为powerset中的每个现有元素添加一个新元素,其中将列表中的当前元素追加到powerset中的现有元素中。

这就是我认为应该以嵌套的方式使用foldr 两次的原因--一种是检查给定列表中的所有项,而对于每一项,我使用foldr来检查“结果”(当前的powerset)中的所有项。

我遇到了空列表的问题(在powerset中没有添加任何内容),因此添加了"if“部分(而不仅仅是foldr),但它也不能很好地工作。

我想就是这样了。我感觉很亲密,但这仍然是很有挑战性的,所以我们会欢迎所有的帮助。谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-18 13:30:17

解决方案更简单,不需要使用双foldr,请尝试如下:

代码语言:javascript
复制
(define (powerset-fr lst)
  (foldr (lambda (e acc)
           (append (map (lambda (x) (cons e x)) 
                        acc) 
                   acc))
         '(())
         lst))

如果您的解释器定义了append-map或类似的东西,那么解决方案就会更短一些--结果将以不同的顺序进行,但这并不重要:

代码语言:javascript
复制
(define (powerset-fr lst)
  (foldr (lambda (e acc)
           (append-map (lambda (x) (list x (cons e x)))
                       acc))
         '(())
         lst))

无论是哪种方式,它都如预期的那样工作:

代码语言:javascript
复制
(powerset-fr '(1 2 3))
=> '((1 2 3) (1 2) (1 3) (1) (2 3) (2) (3) ())
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42874235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档