我尝试编写一个Scheme函数,该函数接受两个参数,一个数字列表和另一个数字,如果列表的一个子集加起来,则返回true。
示例输出:
> (groupSum '(1 2 5) 7)
> #t
> (groupSum '(1 2 5) 4)
> f
到目前为止,我所能做的就是获取列表中所有数字的总和。我需要用我的代码来实现示例输出?
到目前为止,这是我的代码:
(define (groupSum elemList)
(if
(null? elemList)
0
(+ (car elemList) (groupSum (cdr elemList)))
))
我的代码返回的内容:
> (groupSum '(1 2 5))
> 8
答案 0 :(得分:0)
所以你要问的是,给定列表的子集是否存在(在位置意义上,即保留重复,如果有的话),它们加起来给定的数字。
要通过子集是powerset
函数的工作,除非我们想要跳出它并在检测到成功后立即返回#t
。否则,最后只返回#f
。
在此网站上从one of my other answers扩充powerset功能,我们得到
(define (group-adds-to aL aN)
(call/cc
(lambda (......) ;; 2.
(letrec
([...... (lambda (aL) ;; 4.
(cond
[(empty? aL) (list empty)]
[else
(add-into ;; 5b.
(powerset (rest aL)) ;; 3b.
(first aL))]))]
[...... (lambda (r a) ;; 6. ; `r` is recursive result, `a` an element
(cond
[(empty? r) empty] ; nothing to add `a` to
[else
(cons (add a (first r)) ;; 7. ; either add `a`,
(cons (first r) ; or not, to the first in `r`
(add-into ;; 5a. ; and recursively proceed
(rest r) ; to add `a` into the rest of `r`
a )))]))]
[...... ;; 8.
(lambda (......) ;; 9...
(let ([sum ......]) ;; 10...
(if (= sum aN) ;; 11.
(return #t) ;; 1.
sum)))])
(powerset aL) ;; 3a.
#f)))) ;; 12.
填空;
测试:
> (group-adds-to '(1 2 5) 7)
#t
> (group-adds-to '(1 2 5) 4)
#f
如果需要,可以进行一些微不足道的更改,使#r5rs
符合要求。
当然,通过使用更多内置函数,可以简化和缩短此代码。在这里摆脱call/cc
也很简单。您还可以获得想象并添加检查以缩短临时列表,检测并删除不可能有助于成功结果的子组(子集)。
好的,如何填补空白。
return
?那是什么?call/cc
为我们设置的逃生延续。当( if )被调用时,;; 1.
会立即返回值#t
,作为整个group-adds-to
函数调用的最终结果,无论是我们在这一点上的递归内部有多深。递归刚刚放弃,结果只是返回
如果从未调用过return
,因为从未检测到等式(= sum aN) ;; 11.
,递归将结束,#f
将正常返回,作为函数体内的最后一个表达式,在;; 12.
。powerset
?什么是 ?add-into
?add
?;; 7
,它的论点是什么,它必须返回什么。