SICP Exercise 2.32
Question
We can represent a set as a list of distinct elements, and we can represent
the set of all subsets of the set as a list of lists. For example, if the
set is (1 2 3)
, then the set of all subsets is (() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))
. Complete the following definition of a procedure
that generates the set of subsets of a set and give a clear explanation of
why it works:
(define (subsets s)
(if (null? s)
(list nil)
(let ((rest (subsets (cdr s))))
(append rest (map ⟨??⟩ rest)))))
Answer
To figure this out, it helps to look at what the code that we already have
does by itself. Looks like the code gets the cdr
of the list and
recursively calls subsets
on this sublist. If we trust the authors that
this procedure actually does what it says it does, then this rest
variable should be equivalent to (subsets (cdr (1 2 3)))
or, in other
words, (subsets (2 3))
, so all the subsets of the list (2 3)
.
And now if we think about what we expect the total result of the procedure
to be, this starts to make sense. Because the total result is nothing
other than the subsets of (2 3)
plus all these same sublists with a 1
in them, we can guess that the part which is appended to (sublists (2 3))
(aka rest
) must be each element of rest
with a 1
(nothing other than
(car s)
) cons
’d to it. So the lambda function within map
must be
(λ (x) (cons (car s) x))
. This is what the code looks like:
(define (subsets s)
(if (null? s)
(list nil)
(let ((rest (subsets (cdr s))))
(append rest (map (λ (x) (cons (car s) x)) rest)))))
(subsets (list 1 2 3))
Results:
(() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))