« Back to James's CS61A page. | CS61A: Spring 2000 |
It takes only a bit of cleverness to come up with the iterative Fibonacci algorithm. In contrast, consider the following problem: How many different ways can we make change of $1.00, given half-dollars, quarters, dimes, nickels, and pennies? More generally, can we write a procedure to compute the number of ways to change any given amount of money?
This problem has a simple solution as a recursive procedure. Suppose we think of the types of coins available as arranged in some order. Then the following relation holds:
The number of ways to change amount a using n kinds of coins equals
To see why this is true, observe that the ways to make change can be divided into two groups: those that do not use any of the first kind of coin, and those that do. Therefore, the total number of ways to make change for some amount is equal to the number of ways to make change for the amount without using any of the first kind of coin, plus the number of ways to make change assuming that we do use the first kind of coin. But the latter number is equal to the number of ways to make change for the amount that remains after using a coin of the first kind. [Don't worry if you can't understand this very poorly written paragraph. --James]
Thus, we can recursively reduce the problem of changing a given amount to the problem of changing smaller amounts using fewer kinds of coins. Consider this reduction rule carefully, and convince yourself that we can use it to describe an algorithm if we specify the following degenerate cases:
We can easily translate this description into a recursive procedure:
(define (count-change amount) (cc amount 5)) (define (cc amount kinds-of-coins) (cond ((= amount 0) 1) ((or (< amount 0) (= kinds-of-coins 0)) 0) (else (+ (cc amount (- kinds-of-coins 1)) (cc (- amount (first-denomination kinds-of-coins)) kinds-of-coins))))) (define (first-denomination kinds-of-coins) (cond ((= kinds-of-coins 1) 1) ((= kinds-of-coins 2) 5) ((= kinds-of-coins 3) 10) ((= kinds-of-coins 4) 25) ((= kinds-of-coins 5) 50) ))
(The
(count-change 100) 292
[Abelson and Sussman. The Structure and Interpretation of Computer Programs. 2nd edition. pp
exercise 2.2
Consider the problem of representing line segments in a plane. Each
segment is reprsented as a pair of points: a starting point and an ending
point. Define a constructor
(define (print-point p) (newline) (display "(") (display (x-point p)) (display ",") (display (y-point p)) (display ")"))
exercise 2.3
Implement a representation for rectangles in a plane. (Hint: You may want to make use of exercise 2.2.) In terms of your constructors and selectors, create procedures that compute the perimeter and the area of a given rectangle. Now implement a different representation for rectangles. Can you design your system with suitable abstraction barriers, so that the same perimeter and area procedures will work with either representation?
exercise 2.4
Here is an alternate procedural representation of pairs. For this
representation, verify that
(define (new-cons x y) (lambda (m) (m x y))) (define (new-car z) (z (lambda (p q) p)))
What is the corresponding definition of
exercise 2.18
Define a procedure reverse that takes a list as argument and returns a list of the same elements in reverse order:
(reverse (list 1 4 9 16 25)) (25 16 9 4 1)
[Abelson and Sussman. The Structure and Interpretation of Computer Programs. 2nd edition.]
exercise 2.25
Give combinations of cars and cdrs that will pick 7 from each of the following lists:
(1 3 (5 7) 9) ((7)) (1 (2 (3 (4 (5 (6 7))))))
exercise 2.53
What would the interpreter print in response to evaluating each of the following expressions?
(list 'a 'b 'c) (list (list 'george)) (cdr '((x1 x2) (y1 y2))) (cadr '((x1 x2) (y1 y2))) (pair? (car '(a short list))) (memq 'red '((red shoes) (blue socks))) (memq 'red '(red shoes blue socks))
exercise 2.55
Eva Lu Ator types to the interpreter the expression
(car ''abracadabra)
To her surprise, the interpreter prints back quote. Explain.
exercise 2.27
Modify your reverse procedure of exercise 2.18 to produce a
(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))
exercise 2.62
Give a
Code from pp 156-157:
(define (entry tree) (car tree)) (define (left-branch tree) (cadr tree)) (define (right-branch tree) (caddr tree)) (define (make-tree entry left right) (list entry left right)) (define (element-of-set? x set) (cond ((null? set) false) ((= x (entry set)) true) ((< x (entry set)) (element-of-set? x (left-branch set))) ((> x (entry set)) (element-of-set? x (right-branch set))))) (define (adjoin-set x set) (cond ((null? set) (make-tree x '() '())) ((= x (entry set)) set) ((< x (entry set)) (make-tree (entry set) (adjoin-set x (left-branch set)) (right-branch set))) ((> x (entry set)) (make-tree (entry set) (left-branch set) (adjoin-set x (left-branch set))))))
Trees from p 156:
7 3 5 / \ / \ / \ 3 9 1 7 3 9 / \ \ / \ / / \ 1 5 11 5 9 1 7 11 \ 11
exercise 2.74
Insatiable Enterprises, Inc., is a highly decentralized conglomerate company consisting of a large number of independent divisions located all over the world. The company's computer facilities have just been interconnected by means of a clever network-interfacing scheme that makes the entire network appear to any user to be a single computer. Insatiable's president, in her first attempt to exploit the ability of the network to extract administrative information from division files, is dismayed to discover that, although all the division files have been implemented as data structures in Scheme, the particular data structure used varies from division to division. A meeting of division managers is hastily called to search for a strategy to integrate the files that will satisfy headquarters' needs while preserving the existing autonomy of the divisions.
Show how such a strategy can be implemented with data-directed programming. As an example, suppose that each division's personnel records consist of a single file, which contains a set of records keyed on employees' names. The structure of the set varies from division to division. Furthermore, each employee's record is itself a set (structured differently from division to division) that contains information keyed under identifiers such as address and salary. In particular:
a. Implement for headquarters a
b. Implement for headquarters a
c. Implement for headquarters a
d. When Insatiable takes over a new company, what changes must be made in order to incorporate the new personnel information into the central system?
[Abelson and Sussman. The Structure and Interpretation of Computer Programs. 2nd edition.]
exercise 3.12
The following procedure for appending lists was introduced in section 2.2.1:
(define (append x y) (if (null? x) y (cons (car x) (append (cdr x) y))))
Append forms a new list by successively consing the elements of x onto y. The procedure append! is similar to append, but it is a mutator rather than a constructor. It appends the lists by splicing them together, modifying the final pair of x so that its cdr is now y. (It is an error to call append! with an empty x.)
(define (append! x y) (set-cdr! (last-pair x) y) x)
Here,
(define (last-pair x) (if (null? (cdr x)) x (last-pair (cdr x))))
Consider the interaction:
(define x (list 'a 'b)) (define y (list 'c 'd)) (define z (append x y)) z (a b c d) (cdr x) <response> (define w (append! x y)) w (a b c d) (cdr x) <response>
What are the missing <response>s? Draw box-and-pointer diagrams to explain your answer.
exercise 3.13
Consider the following
(define (make-cycle x) (set-cdr! (last-pair x) x) x)
Draw a box-and-pointer diagram that shows the structure z created by:
(define z (make-cycle (list 'a 'b 'c)))
What happens if we try to compute
exercise 3.14
The following procedure is quite useful, although obscure:
(define (mystery x) (define (loop x y) (if (null? x) y (let ((temp (cdr x))) (set-cdr! x y) (loop temp x)))) (loop x '()))
Loop uses the "temporary" variable temp to hold
the old value of the cdr of x, since the
[Abelson and Sussman. The Structure and Interpretation of Computer Programs. 2nd edition.]
Necessary files:
exercise 4.1
Notice that we cannot tell whether the metacircular evaluator evaluates
operands from left to right or from right to left. Its evaluation order is
inherited from the underlying Lisp: If the arguments to cons in
Write a version of
exercise 4.2
Louis Reasoner plans to reorder the cond clauses in
a. What is wrong with Louis's plan? (Hint: What will Louis's evaluator
do with the expression
b. Louis is upset that his plan didn't work. He is willing to go to
any lengths to make his evaluator recognize procedure applications before
it checks for most other kinds of expressions. Help him by changing the
syntax for the evaluated language so that procedure applications start with
call. For example, instead of
exercise 4.4
Recall the definitions of the special forms and and or from chapter 1:
Install and and or as new special forms for the evaluator
by defining appropriate syntax procedures and evaluation procedures
exercise 4.5
Scheme allows an additional syntax for cond clauses,
(cond ((assoc 'b '((a 1) (b 2))) => cadr) (else false))
Returns 2. Modifying the handling of cond so that it supports this extended syntax.
[Abelson and Sussman. The Structure and Interpretation of Computer Programs. 2nd edition.]
Necessary files:
exercise 4.27
Suppose we type in the following definitions to the lazy evaluator:
(define count 0) (define (id x) (set! count (+ count 1)) x)
Give the missing values in the following sequence of interactions, and explain your answers.
(define w (id (id 10))) ;;; L-Eval input: count ;;; L-Eval value: <response> ;;; L-Eval input: w ;;; L-Eval value: <response> ;;; L-Eval input: count ;;; L-Eval value: <response>
exercise 4.29
Exhibit a program that you would expect to run much more slowly without memoization than with memoization. Also, consider the following interaction, where the id procedure is defined as in exercise 4.27 and count starts at 0:
(define (square x) (* x x)) ;;; L-Eval input: (square (id 10)) ;;; L-Eval value: <response> ;;; L-Eval input: count ;;; L-Eval value: <response>
Give the responses both when the evaluator memoizes and when it does not.
[Abelson and Sussman. The Structure and Interpretation of Computer Programs. 2nd edition.]
Need help with Logo? In the Logo interpreter, type help to see a list of commands and operators. You can also type
to get help on a particular item.
Create a procedure and want to change it? You can erase previously defined procedures from the environment with:
Necessary files:
exercise 4.35
Write a procedure
(define (a-pythagorean-triple-between low high) (let ((i (an-integer-between low high))) (let ((j (an-integer-between i high))) (let ((k (an-integer-between j high))) (require (= (+ (* i i) (* j j)) (* k k))) (list i j k) ))))
The following puzzle (taken from Dinesman 1968) is typical of a large class of simple logic puzzles:
Baker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house that contains only five floors. Baker does not live on the top floor. Cooper does not live on the bottom floor. Fletcher does not live on either the top or the bottom floor. Miller lives on a higher floor than does Cooper. Smith does not live on a floor adjacent to Fletcher's. Fletcher does not live on a floor adjacent to Cooper's. Where does everyone live?
We can determine who lives on each floor in a straightforward way by enumerating all the possibilities and imposing the given restrictions*:
(define (multiple-dwelling) (let ((baker (amb 1 2 3 4 5)) (cooper (amb 1 2 3 4 5)) (fletcher (amb 1 2 3 4 5)) (miller (amb 1 2 3 4 5)) (smith (amb 1 2 3 4 5))) (require (distinct? (list baker cooper fletcher miller smith))) (require (not (= baker 5))) (require (not (= cooper 1))) (require (not (= fletcher 5))) (require (not (= fletcher 1))) (require (> miller cooper)) (require (not (= (abs (- smith fletcher)) 1))) (require (not (= (abs (- fletcher cooper)) 1))) (list (list 'baker baker) (list 'cooper cooper) (list 'fletcher fletcher) (list 'miller miller) (list 'smith smith)) ))
Evaluating the expression
Although this simple procedure works, it is very slow. Exercises 4.39 and 4.40 discuss some possible improvements.
* Our program uses the following procedure to determine if the elements of a list are distinct:
(define (distinct? items) (cond ((null? items) true) ((null? (cdr items)) true) ((member (car items) (cdr items)) false) (else (distinct? (cdr items))) ))
Member is like memq except that it uses equal? instead of eq? to test for equality.
exercise 4.38
Modify the multiple-dwelling procedure to omit the requirement that Smith and Fletcher do not live on adjacent floors. How many solutions are there to this modified puzzle?
[Abelson and Sussman. The Structure and Interpretation of Computer Programs. 2nd edition. pp
« Back to James's CS61A page. | CS61A: Spring 2000 |
Last Modified: Tuesday, 30-Dec-2014 11:58:34 PST