mirror of
https://github.com/correl/sicp.git
synced 2024-11-23 19:19:56 +00:00
687 lines
21 KiB
Org Mode
687 lines
21 KiB
Org Mode
|
#+BEGIN_HTML
|
||
|
---
|
||
|
title: 2.2 - Hierarchical Data and the Closure Property
|
||
|
layout: org
|
||
|
---
|
||
|
#+END_HTML
|
||
|
|
||
|
* Representing Sequences
|
||
|
** List Operations
|
||
|
*** Exercise 2.17
|
||
|
Define a procedure `last-pair' that returns the
|
||
|
list that contains only the last element of a given (nonempty)
|
||
|
list:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(last-pair (list 23 72 149 34))
|
||
|
(34)
|
||
|
#+end_src
|
||
|
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.17
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define (last-pair list)
|
||
|
(cond ((null? list) ())
|
||
|
((null? (cdr list)) list)
|
||
|
(else (last-pair (cdr list)))))
|
||
|
#+end_src
|
||
|
*** Exercise 2.18
|
||
|
Define a procedure `reverse' that takes a list as
|
||
|
argument and returns a list of the same elements in reverse order:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(reverse (list 1 4 9 16 25))
|
||
|
(25 16 9 4 1)
|
||
|
#+end_src
|
||
|
|
||
|
--------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.18
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define (reverse list)
|
||
|
(define (iter original new)
|
||
|
(if (null? original) new
|
||
|
(let ((head (car original))
|
||
|
(tail (cdr original)))
|
||
|
(iter tail (cons head new)))))
|
||
|
(iter list ()))
|
||
|
#+end_src
|
||
|
|
||
|
*** Exercise 2.19
|
||
|
Consider the change-counting program of section
|
||
|
*Note 1-2-2::. It would be nice to be able to easily change the
|
||
|
currency used by the program, so that we could compute the number
|
||
|
of ways to change a British pound, for example. As the program is
|
||
|
written, the knowledge of the currency is distributed partly into
|
||
|
the procedure `first-denomination' and partly into the procedure
|
||
|
`count-change' (which knows that there are five kinds of U.S.
|
||
|
coins). It would be nicer to be able to supply a list of coins to
|
||
|
be used for making change.
|
||
|
|
||
|
We want to rewrite the procedure `cc' so that its second argument
|
||
|
is a list of the values of the coins to use rather than an integer
|
||
|
specifying which coins to use. We could then have lists that
|
||
|
defined each kind of currency:
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.19
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define us-coins (list 50 25 10 5 1))
|
||
|
|
||
|
(define uk-coins (list 100 50 20 10 5 2 1 0.5))
|
||
|
#+end_src
|
||
|
|
||
|
We could then call `cc' as follows:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(cc 100 us-coins)
|
||
|
292
|
||
|
#+end_src
|
||
|
|
||
|
To do this will require changing the program `cc' somewhat. It
|
||
|
will still have the same form, but it will access its second
|
||
|
argument differently, as follows:
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
(define (cc amount coin-values)
|
||
|
(cond ((= amount 0) 1)
|
||
|
((or (< amount 0) (no-more? coin-values)) 0)
|
||
|
(else
|
||
|
(+ (cc amount
|
||
|
(except-first-denomination coin-values))
|
||
|
(cc (- amount
|
||
|
(first-denomination coin-values))
|
||
|
coin-values)))))
|
||
|
#+end_src
|
||
|
|
||
|
Define the procedures `first-denomination',
|
||
|
`except-first-denomination', and `no-more?' in terms of primitive
|
||
|
operations on list structures. Does the order of the list
|
||
|
`coin-values' affect the answer produced by `cc'? Why or why not?
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
(define first-denomination car)
|
||
|
(define except-first-denomination cdr)
|
||
|
(define no-more? null?)
|
||
|
#+end_src
|
||
|
|
||
|
*** Exercise 2.20
|
||
|
The procedures `+', `*', and `list' take
|
||
|
arbitrary numbers of arguments. One way to define such procedures
|
||
|
is to use `define' with notation "dotted-tail notation". In a
|
||
|
procedure definition, a parameter list that has a dot before the
|
||
|
last parameter name indicates that, when the procedure is called,
|
||
|
the initial parameters (if any) will have as values the initial
|
||
|
arguments, as usual, but the final parameter's value will be a "list"
|
||
|
of any remaining arguments. For instance, given the definition
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (f x y . z) <BODY>)
|
||
|
#+end_src
|
||
|
|
||
|
the procedure `f' can be called with two or more arguments. If we
|
||
|
evaluate
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(f 1 2 3 4 5 6)
|
||
|
#+end_src
|
||
|
|
||
|
then in the body of `f', `x' will be 1, `y' will be 2, and `z'
|
||
|
will be the list `(3 4 5 6)'. Given the definition
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (g . w) <BODY>)
|
||
|
#+end_src
|
||
|
|
||
|
the procedure `g' can be called with zero or more arguments. If we
|
||
|
evaluate
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(g 1 2 3 4 5 6)
|
||
|
#+end_src
|
||
|
|
||
|
then in the body of `g', `w' will be the list `(1 2 3 4 5 6)'.(4)
|
||
|
|
||
|
Use this notation to write a procedure `same-parity' that takes
|
||
|
one or more integers and returns a list of all the arguments that
|
||
|
have the same even-odd parity as the first argument. For example,
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(same-parity 1 2 3 4 5 6 7)
|
||
|
(1 3 5 7)
|
||
|
|
||
|
(same-parity 2 3 4 5 6 7)
|
||
|
(2 4 6)
|
||
|
#+end_src
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.20
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define (same-parity n . rest)
|
||
|
(define (iter predicate original filtered)
|
||
|
(cond ((null? original) filtered)
|
||
|
((predicate (car original))
|
||
|
(iter predicate
|
||
|
(cdr original)
|
||
|
(append filtered (list (car original)))))
|
||
|
(else (iter predicate
|
||
|
(cdr original)
|
||
|
filtered))))
|
||
|
(iter (if (even? n) even? odd?)
|
||
|
(cons n rest)
|
||
|
'()))
|
||
|
#+end_src
|
||
|
|
||
|
** Mapping over lists
|
||
|
*** Exercise 2.21:
|
||
|
The procedure `square-list' takes a list of numbers as argument
|
||
|
and returns a list of the squares of those numbers.
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(square-list (list 1 2 3 4))
|
||
|
(1 4 9 16)
|
||
|
#+end_src
|
||
|
|
||
|
Here are two different definitions of `square-list'. Complete
|
||
|
both of them by filling in the missing expressions:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (square-list items)
|
||
|
(if (null? items)
|
||
|
nil
|
||
|
(cons <??> <??>)))
|
||
|
|
||
|
(define (square-list items)
|
||
|
(map <??> <??>))
|
||
|
#+end_src
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.21
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define (square-list items)
|
||
|
(if (null? items)
|
||
|
'()
|
||
|
(cons (* (car items) (car items)) (square-list (cdr items)))))
|
||
|
|
||
|
(define (square-list items)
|
||
|
(map (lambda (x) (* x x))
|
||
|
items))
|
||
|
#+end_src
|
||
|
|
||
|
*** Exercise 2.22:
|
||
|
Louis Reasoner tries to rewrite the first `square-list' procedure
|
||
|
of *Note Exercise 2-21:: so that it evolves an iterative process:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (square-list items)
|
||
|
(define (iter things answer)
|
||
|
(if (null? things)
|
||
|
answer
|
||
|
(iter (cdr things)
|
||
|
(cons (square (car things))
|
||
|
answer))))
|
||
|
(iter items nil))
|
||
|
#+end_src
|
||
|
|
||
|
Unfortunately, defining `square-list' this way produces the answer
|
||
|
list in the reverse order of the one desired. Why?
|
||
|
|
||
|
Louis then tries to fix his bug by interchanging the arguments to
|
||
|
`cons':
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (square-list items)
|
||
|
(define (iter things answer)
|
||
|
(if (null? things)
|
||
|
answer
|
||
|
(iter (cdr things)
|
||
|
(cons answer
|
||
|
(square (car things))))))
|
||
|
(iter items nil))
|
||
|
#+end_src
|
||
|
|
||
|
This doesn't work either. Explain.
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
The first iterative rewrite reads the items from first to last,
|
||
|
but builds the list last to first (cons effectively prepends the
|
||
|
answer to the list of results).
|
||
|
|
||
|
The second version attempts to reverse the arguments of cons,
|
||
|
however this doesn't build a proper list. Normally, a list is a
|
||
|
value paired with a list in the second slot. This pairs a list
|
||
|
with a value in the second slot.
|
||
|
|
||
|
*** Exercise 2.23
|
||
|
The procedure `for-each' is similar to `map'. It takes as
|
||
|
arguments a procedure and a list of elements. However, rather
|
||
|
than forming a list of the results, `for-each' just applies the
|
||
|
procedure to each of the elements in turn, from left to right.
|
||
|
The values returned by applying the procedure to the elements are
|
||
|
not used at all--`for-each' is used with procedures that perform
|
||
|
an action, such as printing. For example,
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(for-each (lambda (x) (newline) (display x))
|
||
|
(list 57 321 88))
|
||
|
57
|
||
|
321
|
||
|
88
|
||
|
#+end_src
|
||
|
|
||
|
The value returned by the call to `for-each' (not illustrated
|
||
|
above) can be something arbitrary, such as true. Give an
|
||
|
implementation of `for-each'.
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.23
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define (for-each fun list)
|
||
|
(if (null? list)
|
||
|
#t
|
||
|
))
|
||
|
|
||
|
#+end_src
|
||
|
* Hierarchical Structures
|
||
|
** Exercise 2.24
|
||
|
Suppose we evaluate the expression `(list 1 (list
|
||
|
2 (list 3 4)))'. Give the result printed by the interpreter, the
|
||
|
corresponding box-and-pointer structure, and the interpretation of
|
||
|
this as a tree (as in *Note Figure 2-6::).
|
||
|
|
||
|
-------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.24
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
'(1 (2 (3 4)))
|
||
|
|
||
|
;; [ * | * ]
|
||
|
;; ↓ ↓
|
||
|
;; 1 [ * | * ]
|
||
|
;; ↓ ↓
|
||
|
;; 2 [ * | * ] → [ * | / ]
|
||
|
;; ↓ ↓
|
||
|
;; 3 4
|
||
|
|
||
|
;; *
|
||
|
;; / \
|
||
|
;; 1 *
|
||
|
;; / \
|
||
|
;; 2 *
|
||
|
;; / \
|
||
|
;; 3 4
|
||
|
#+end_src
|
||
|
|
||
|
** Exercise 2.25
|
||
|
Give combinations of `car's and `cdr's that will
|
||
|
pick 7 from each of the following lists:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(1 3 (5 7) 9)
|
||
|
|
||
|
((7))
|
||
|
|
||
|
(1 (2 (3 (4 (5 (6 7))))))
|
||
|
#+end_src
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.25
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(car (cdr (car (cdr (cdr '(1 3 (5 7) 9))))))
|
||
|
|
||
|
(car (car '((7))))
|
||
|
|
||
|
(car (cdr (car (cdr (car (cdr (car (cdr (car (cdr (car (cdr '(1 (2 (3 (4 (5 (6 7))))))))))))))))))
|
||
|
#+end_src
|
||
|
|
||
|
** Exercise 2.26
|
||
|
Suppose we define `x' and `y' to be two lists:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define x (list 1 2 3))
|
||
|
|
||
|
(define y (list 4 5 6))
|
||
|
#+end_src
|
||
|
|
||
|
What result is printed by the interpreter in response to
|
||
|
evaluating each of the following expressions:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(append x y)
|
||
|
|
||
|
(cons x y)
|
||
|
|
||
|
(list x y)
|
||
|
#+end_src
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.26
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
;; (append x y)
|
||
|
'(1 2 3 4 5 6)
|
||
|
|
||
|
;; (cons x y)
|
||
|
'((1 2 3) 4 5 6)
|
||
|
|
||
|
;; (list x y)
|
||
|
'((1 2 3) (4 5 6))
|
||
|
#+end_src
|
||
|
|
||
|
** Exercise 2.27
|
||
|
Modify your `reverse' procedure of *Note Exercise
|
||
|
2-18:: to produce a `deep-reverse' procedure that takes a list as
|
||
|
argument and returns as its value the list with its elements
|
||
|
reversed and with all sublists deep-reversed as well. For example,
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define x (list (list 1 2) (list 3 4)))
|
||
|
|
||
|
x
|
||
|
((1 2) (3 4))
|
||
|
|
||
|
(reverse x)
|
||
|
((3 4) (1 2))
|
||
|
|
||
|
(deep-reverse x)
|
||
|
((4 3) (2 1))
|
||
|
#+end_src
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.27
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define (deep-reverse list)
|
||
|
(define (iter original new)
|
||
|
(if (null? original) new
|
||
|
(let ((head (car original))
|
||
|
(tail (cdr original)))
|
||
|
(iter tail (cons
|
||
|
(if (pair? head)
|
||
|
(deep-reverse head)
|
||
|
head)
|
||
|
new)))))
|
||
|
(iter list ()))
|
||
|
|
||
|
#+end_src
|
||
|
|
||
|
** Exercise 2.28
|
||
|
Write a procedure `fringe' that takes as argument
|
||
|
a tree (represented as a list) and returns a list whose elements
|
||
|
are all the leaves of the tree arranged in left-to-right order.
|
||
|
For example,
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define x (list (list 1 2) (list 3 4)))
|
||
|
|
||
|
(fringe x)
|
||
|
(1 2 3 4)
|
||
|
|
||
|
(fringe (list x x))
|
||
|
(1 2 3 4 1 2 3 4)
|
||
|
#+end_src
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (fringe tree)
|
||
|
(define (iter original new)
|
||
|
(if (null? original) new
|
||
|
(let ((head (car original))
|
||
|
(tail (cdr original)))
|
||
|
(if (pair? head)
|
||
|
(iter (append head tail) new)
|
||
|
(iter tail (cons head new))))))
|
||
|
(iter (deep-reverse tree) '()))
|
||
|
#+end_src
|
||
|
|
||
|
** Exercise 2.29
|
||
|
A binary mobile consists of two branches, a left
|
||
|
branch and a right branch. Each branch is a rod of a certain
|
||
|
length, from which hangs either a weight or another binary mobile.
|
||
|
We can represent a binary mobile using compound data by
|
||
|
constructing it from two branches (for example, using `list'):
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (make-mobile left right)
|
||
|
(list left right))
|
||
|
#+end_src
|
||
|
|
||
|
A branch is constructed from a `length' (which must be a number)
|
||
|
together with a `structure', which may be either a number
|
||
|
(representing a simple weight) or another mobile:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (make-branch length structure)
|
||
|
(list length structure))
|
||
|
#+end_src
|
||
|
|
||
|
a. Write the corresponding selectors `left-branch' and
|
||
|
`right-branch', which return the branches of a mobile, and
|
||
|
`branch-length' and `branch-structure', which return the
|
||
|
components of a branch.
|
||
|
|
||
|
b. Using your selectors, define a procedure `total-weight' that
|
||
|
returns the total weight of a mobile.
|
||
|
|
||
|
c. A mobile is said to be "balanced" if the torque applied by
|
||
|
its top-left branch is equal to that applied by its top-right
|
||
|
branch (that is, if the length of the left rod multiplied by
|
||
|
the weight hanging from that rod is equal to the
|
||
|
corresponding product for the right side) and if each of the
|
||
|
submobiles hanging off its branches is balanced. Design a
|
||
|
predicate that tests whether a binary mobile is balanced.
|
||
|
|
||
|
d. Suppose we change the representation of mobiles so that the
|
||
|
constructors are
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (make-mobile left right)
|
||
|
(cons left right))
|
||
|
|
||
|
(define (make-branch length structure)
|
||
|
(cons length structure))
|
||
|
#+end_src
|
||
|
|
||
|
How much do you need to change your programs to convert to
|
||
|
the new representation?
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.29
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define (make-mobile left right)
|
||
|
(list left right))
|
||
|
|
||
|
(define (make-branch length structure)
|
||
|
(list length structure))
|
||
|
|
||
|
(define left-branch car)
|
||
|
(define right-branch cadr)
|
||
|
|
||
|
(define branch-length car)
|
||
|
(define branch-structure cadr)
|
||
|
|
||
|
;; Test Data
|
||
|
;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
(define (make-test-mobile)
|
||
|
(make-mobile
|
||
|
(make-branch 3 4)
|
||
|
(make-branch 1
|
||
|
(make-mobile
|
||
|
(make-branch 1 10)
|
||
|
(make-branch 5 2)))))
|
||
|
|
||
|
;; Calculations
|
||
|
;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
(define (branch-weight branch)
|
||
|
(let ((structure (branch-structure branch)))
|
||
|
(if (number? structure)
|
||
|
structure
|
||
|
(+ (branch-weight (left-branch structure))
|
||
|
(branch-weight (right-branch structure))))))
|
||
|
|
||
|
(define (total-weight mobile)
|
||
|
(+ (branch-weight (left-branch mobile))
|
||
|
(branch-weight (right-branch mobile))))
|
||
|
|
||
|
(define (torque branch)
|
||
|
(* (branch-length branch)
|
||
|
(branch-weight branch)))
|
||
|
|
||
|
(define (balanced? mobile)
|
||
|
(define (balanced-branch? branch)
|
||
|
(let ((structure (branch-structure branch)))
|
||
|
(if (number? structure)
|
||
|
#t
|
||
|
(balanced? structure))))
|
||
|
(let ((left (left-branch mobile))
|
||
|
(right (right-branch mobile)))
|
||
|
(and
|
||
|
(= (torque left)
|
||
|
(torque right))
|
||
|
(and (balanced-branch? left)
|
||
|
(balanced-branch? right)))))
|
||
|
|
||
|
;; New representation
|
||
|
;; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
(define (make-mobile left right)
|
||
|
(cons left right))
|
||
|
|
||
|
(define (make-branch length structure)
|
||
|
(cons length structure))
|
||
|
|
||
|
(define right-branch cdr)
|
||
|
(define branch-structure cdr)
|
||
|
#+end_src
|
||
|
** Mapping over trees
|
||
|
*** Exercise 2.30
|
||
|
Define a procedure `square-tree' analogous to the `square-list'
|
||
|
procedure of *Note Exercise 2-21::. That is, `square-list' should
|
||
|
behave as follows:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(square-tree
|
||
|
(list 1
|
||
|
(list 2 (list 3 4) 5)
|
||
|
(list 6 7)))
|
||
|
(1 (4 (9 16) 25) (36 49))
|
||
|
#+end_src
|
||
|
|
||
|
Define `square-tree' both directly (i.e., without using any
|
||
|
higher-order procedures) and also by using `map' and recursion.
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.30
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define (square-tree tree)
|
||
|
(cond ((null? tree) '())
|
||
|
((not (pair? tree)) (square tree))
|
||
|
(else (cons (square-tree (car tree))
|
||
|
(square-tree (cdr tree))))))
|
||
|
|
||
|
(define (square-tree tree)
|
||
|
(map (lambda (sub-tree)
|
||
|
(if (pair? sub-tree)
|
||
|
(square-tree sub-tree)
|
||
|
(square sub-tree)))
|
||
|
tree))
|
||
|
#+end_src
|
||
|
*** Exercise 2.31
|
||
|
Abstract your answer to *Note Exercise 2-30:: to produce a
|
||
|
procedure `tree-map' with the property that `square-tree' could be
|
||
|
defined as
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (square-tree tree) (tree-map square tree))
|
||
|
#+end_src
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
;; -------------------------------------------------------------------
|
||
|
;; Exercise 2.31
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define (tree-map f tree)
|
||
|
(map (lambda (sub-tree)
|
||
|
(if (pair? sub-tree)
|
||
|
(tree-map f sub-tree)
|
||
|
(f sub-tree)))
|
||
|
tree))
|
||
|
|
||
|
(define (square-tree tree)
|
||
|
(tree-map square tree))
|
||
|
#+end_src
|
||
|
*** Exercise 2.32
|
||
|
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:
|
||
|
|
||
|
#+begin_src scheme
|
||
|
(define (subsets s)
|
||
|
(if (null? s)
|
||
|
(list nil)
|
||
|
(let ((rest (subsets (cdr s))))
|
||
|
(append rest (map <??> rest)))))
|
||
|
#+end_src
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
#+begin_src scheme :tangle yes
|
||
|
(define (subsets s)
|
||
|
(if (null? s)
|
||
|
(list '())
|
||
|
(let ((rest (subsets (cdr s))))
|
||
|
(append rest (map (lambda (x) (cons (car s) x)) rest)))))
|
||
|
#+end_src
|