So what you ask is, does a subset of a given list exist (in a positional sense, i.e. keeping duplicates, if any) that adds up to a given number.
To go through subsets is the job of the powerset
function, except we want to jump out of it and return #t
as soon as we detect success. Otherwise, just return #f
in the end.
Augmenting a powerset function from one of my other answers on this site, we get
(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.
Fill in the blanks!
Testing:
> (group-adds-to '(1 2 5) 7)
#t
> (group-adds-to '(1 2 5) 4)
#f
It takes a few trivial changes to make this #r5rs
compliant, if you need it to be.
Of course this code can be streamlined and shortened with the use of more built-in functions. It is quite simple to get rid of call/cc
here, too. You can also get fancy and add checks to shorten the interim lists, detecting and removing such subgroups (subsets) that can't possibly contribute to a successful outcome.
OK, how to fill in the blanks.
return
? what is that?
- it is an escape continuation set up for us by
call/cc
. When (if) it is called, as ;; 1.
, the value #t
is returned right away as the final result of the whole group-adds-to
function call, no matter how deep inside the recursion we are at that point. The recursion is just abandoned, and the result is just returned.
And if return
was never called, because the equality (= sum aN) ;; 11.
was never detected, the recursion will end its course and #f
will be returned normally, as the last expression in a function's body, at ;; 12.
.
- a,b.
powerset
? what is that?
- it is an internal function we've defined
- a,b.
add-into
?
- it too, defined here.
- and
add
?
- yep.
- Do it yourself. See how it is used, at
;; 7
, what its arguments are, what must it return.
- Do It Yourself. You can do it!