Add all tasks parsed from a book

master
Aleksey Zubakov 2 years ago
parent 3ea2479745
commit 5cc1e56aa0
  1. 27
      sicp/1_002e1
  2. 41
      sicp/1_002e10
  3. 68
      sicp/1_002e11
  4. 17
      sicp/1_002e12
  5. 85
      sicp/1_002e13
  6. 5
      sicp/1_002e14
  7. 75
      sicp/1_002e15
  8. 67
      sicp/1_002e16
  9. 19
      sicp/1_002e17
  10. 5
      sicp/1_002e18
  11. 203
      sicp/1_002e19
  12. 47
      sicp/1_002e2
  13. 11
      sicp/1_002e20
  14. 4
      sicp/1_002e21
  15. 67
      sicp/1_002e22
  16. 16
      sicp/1_002e23
  17. 17
      sicp/1_002e24
  18. 11
      sicp/1_002e25
  19. 42
      sicp/1_002e26
  20. 23
      sicp/1_002e27
  21. 92
      sicp/1_002e28
  22. 149
      sicp/1_002e29
  23. 4
      sicp/1_002e3
  24. 13
      sicp/1_002e30
  25. 63
      sicp/1_002e31
  26. 25
      sicp/1_002e32
  27. 45
      sicp/1_002e33
  28. 18
      sicp/1_002e34
  29. 21
      sicp/1_002e35
  30. 46
      sicp/1_002e36
  31. 166
      sicp/1_002e37
  32. 28
      sicp/1_002e38
  33. 53
      sicp/1_002e39
  34. 8
      sicp/1_002e4
  35. 27
      sicp/1_002e40
  36. 9
      sicp/1_002e41
  37. 32
      sicp/1_002e42
  38. 110
      sicp/1_002e43
  39. 56
      sicp/1_002e44
  40. 97
      sicp/1_002e45
  41. 15
      sicp/1_002e46
  42. 26
      sicp/1_002e5
  43. 34
      sicp/1_002e6
  44. 11
      sicp/1_002e7
  45. 37
      sicp/1_002e8
  46. 20
      sicp/1_002e9
  47. 6
      sicp/2_002e1
  48. 5
      sicp/2_002e10
  49. 35
      sicp/2_002e11
  50. 6
      sicp/2_002e12
  51. 88
      sicp/2_002e13
  52. 27
      sicp/2_002e14
  53. 8
      sicp/2_002e15
  54. 5
      sicp/2_002e16
  55. 9
      sicp/2_002e17
  56. 9
      sicp/2_002e18
  57. 54
      sicp/2_002e19
  58. 26
      sicp/2_002e2
  59. 47
      sicp/2_002e20
  60. 21
      sicp/2_002e21
  61. 32
      sicp/2_002e22
  62. 22
      sicp/2_002e23
  63. 5
      sicp/2_002e24
  64. 8
      sicp/2_002e25
  65. 15
      sicp/2_002e26
  66. 19
      sicp/2_002e27
  67. 16
      sicp/2_002e28
  68. 48
      sicp/2_002e29
  69. 8
      sicp/2_002e3
  70. 15
      sicp/2_002e30
  71. 8
      sicp/2_002e31
  72. 14
      sicp/2_002e32
  73. 15
      sicp/2_002e33
  74. 182
      sicp/2_002e34
  75. 7
      sicp/2_002e35
  76. 18
      sicp/2_002e36
  77. 250
      sicp/2_002e37
  78. 27
      sicp/2_002e38
  79. 13
      sicp/2_002e39
  80. 14
      sicp/2_002e4
  81. 27
      sicp/2_002e40
  82. 14
      sicp/2_002e41
  83. 142
      sicp/2_002e42
  84. 28
      sicp/2_002e43
  85. 5
      sicp/2_002e44
  86. 11
      sicp/2_002e45
  87. 151
      sicp/2_002e46
  88. 13
      sicp/2_002e47
  89. 7
      sicp/2_002e48
  90. 15
      sicp/2_002e49
  91. 21
      sicp/2_002e5
  92. 4
      sicp/2_002e50
  93. 8
      sicp/2_002e51
  94. 18
      sicp/2_002e52
  95. 12
      sicp/2_002e53
  96. 21
      sicp/2_002e54
  97. 8
      sicp/2_002e55
  98. 59
      sicp/2_002e56
  99. 12
      sicp/2_002e57
  100. 22
      sicp/2_002e58
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,27 @@
Exercise 1.1: Below is a sequence of expressions.
What is the result printed by the interpreter in response to each expression?
Assume that the sequence is to be evaluated in the order in which it is
presented.
10
(+ 5 3 4)
(- 9 1)
(/ 6 2)
(+ (* 2 4) (- 4 6))
(define a 3)
(define b (+ a 1))
(+ a b (* a b))
(= a b)
(if (and (> b a) (< b (* a b)))
b
a)
(cond ((= a 4) 6)
((= b 4) (+ 6 7 a))
(else 25))
(+ 2 (if (> b a) b a))
(* (cond ((> a b) a)
((< a b) b)
(else -1))
(+ a 1))

@ -0,0 +1,41 @@
Exercise 1.10: The following procedure computes
a mathematical function called Ackermann’s function.
(define (A x y)
(cond ((= y 0) 0)
((= x 0) (* 2 y))
((= y 1) 2)
(else (A (- x 1)
(A x (- y 1))))))
What are the values of the following expressions?
(A 1 10)
(A 2 4)
(A 3 3)
Consider the following procedures, where A is the procedure
defined above:
(define (f n) (A 0 n))
(define (g n) (A 1 n))
(define (h n) (A 2 n))
(define (k n) (* 5 n n))
Give concise mathematical definitions for the functions computed by the
procedures f, g, and h for positive integer values of
n
. For example, (k n) computes
5
n
2
.

@ -0,0 +1,68 @@
Exercise 1.11: A function
f
is defined by
the rule that
f
(
n
)
=
n
if
n
<
3
and
f
(
n
)
=
f
(
n
1
)
+
2
f
(
n
2
)
+
3
f
(
n
3
)
if
n
3
.
Write a procedure that computes
f
by means of a recursive process. Write a procedure that
computes
f
by means of an iterative process.

@ -0,0 +1,17 @@
Exercise 1.12: The following pattern of numbers
is called
Pascal’s triangle.
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
. . .
The numbers at the edge of the triangle are all 1, and each number inside the
triangle is the sum of the two numbers above it.35 Write a procedure that computes elements of Pascal’s triangle by
means of a recursive process.

@ -0,0 +1,85 @@
Exercise 1.13: Prove that
Fib
(
n
)
is
the closest integer to
φ
n
/
5
, where
φ
=
(
1
+
5
)
/
2
.
Hint: Let
ψ
=
(
1
5
)
/
2
.
Use induction and the definition of the Fibonacci numbers (see 1.2.2)
to prove that
Fib
(
n
)
=
(
φ
n
ψ
n
)
/
5
.

@ -0,0 +1,5 @@
Exercise 1.14: Draw the tree illustrating the
process generated by the count-change procedure of 1.2.2
in making change for 11 cents. What are the orders of growth of the space and
number of steps used by this process as the amount to be changed increases?

@ -0,0 +1,75 @@
Exercise 1.15: The sine of an angle (specified
in radians) can be computed by making use of the approximation
sin
x
x
if
x
is sufficiently small, and the trigonometric
identity
sin
x
=
3
sin
x
3
4
sin
3
x
3
to reduce the size of the argument of sin. (For purposes of this
exercise an angle is considered “sufficiently small” if its magnitude is not
greater than 0.1 radians.) These ideas are incorporated in the following
procedures:
(define (cube x) (* x x x))
(define (p x) (- (* 3 x) (* 4 (cube x))))
(define (sine angle)
(if (not (> (abs angle) 0.1))
angle
(p (sine (/ angle 3.0)))))
How many times is the procedure p applied when (sine 12.15) is
evaluated?
What is the order of growth in space and number of steps (as a function of
a
) used by the process generated by the sine procedure when
(sine a) is evaluated?

@ -0,0 +1,67 @@
Exercise 1.16: Design a procedure that evolves
an iterative exponentiation process that uses successive squaring and uses a
logarithmic number of steps, as does fast-expt. (Hint: Using the
observation that
(
b
n
/
2
)
2
=
(
b
2
)
n
/
2
, keep, along with
the exponent
n
and the base
b
, an additional state variable
a
, and
define the state transformation in such a way that the product
a
b
n
is unchanged from state to state. At the beginning of the process
a
is taken to be 1, and the answer is given by the value of
a
at the
end of the process. In general, the technique of defining an
invariant quantity that remains unchanged from state to state is a
powerful way to think about the design of iterative algorithms.)

@ -0,0 +1,19 @@
Exercise 1.17: The exponentiation algorithms in
this section are based on performing exponentiation by means of repeated
multiplication. In a similar way, one can perform integer multiplication by
means of repeated addition. The following multiplication procedure (in which
it is assumed that our language can only add, not multiply) is analogous to the
expt procedure:
(define (* a b)
(if (= b 0)
0
(+ a (* a (- b 1)))))
This algorithm takes a number of steps that is linear in b. Now suppose
we include, together with addition, operations double, which doubles an
integer, and halve, which divides an (even) integer by 2. Using these,
design a multiplication procedure analogous to fast-expt that uses a
logarithmic number of steps.

@ -0,0 +1,5 @@
Exercise 1.18: Using the results of
Exercise 1.16 and Exercise 1.17, devise a procedure that generates
an iterative process for multiplying two integers in terms of adding, doubling,
and halving and uses a logarithmic number of steps.40

@ -0,0 +1,203 @@
Exercise 1.19: There is a clever algorithm for
computing the Fibonacci numbers in a logarithmic number of steps. Recall the
transformation of the state variables
a
and
b
in the fib-iter
process of 1.2.2:
a
a
+
b
and
b
a
.
Call this transformation
T
, and observe that applying
T
over and over
again
n
times, starting with 1 and 0, produces the pair
Fib
(
n
+
1
)
and
Fib
(
n
)
. In other words, the Fibonacci numbers are produced
by applying
T
n
, the
n
th
power of the transformation
T
,
starting with the pair (1, 0). Now consider
T
to be the special case of
p
=
0
and
q
=
1
in a family of transformations
T
p
q
,
where
T
p
q
transforms the pair
(
a
,
b
)
according to
a
b
q
+
a
q
+
a
p
and
b
b
p
+
a
q
.
Show that if we apply such a transformation
T
p
q
twice, the
effect is the same as using a single transformation
T
p
q
of the
same form, and compute
p
and
q
in terms of
p
and
q
. This
gives us an explicit way to square these transformations, and thus we can
compute
T
n
using successive squaring, as in the fast-expt
procedure. Put this all together to complete the following procedure, which
runs in a logarithmic number of steps:41
(define (fib n)
(fib-iter 1 0 0 1 n))
(define (fib-iter a b p q count)
(cond ((= count 0)
b)
((even? count)
(fib-iter a
b
⟨??⟩ ;compute p'
⟨??⟩ ;compute q'
(/ count 2)))
(else
(fib-iter (+ (* b q)
(* a q)
(* a p))
(+ (* b p)
(* a q))
p
q
(- count 1)))))

@ -0,0 +1,47 @@
Exercise 1.2: Translate the following expression
into prefix form:
5
+
4
+
(
2
(
3
(
6
+
4
5
)
)
)
3
(
6
2
)
(
2
7
)
.

@ -0,0 +1,11 @@
Exercise 1.20: The process that a procedure
generates is of course dependent on the rules used by the interpreter. As an
example, consider the iterative gcd procedure given above. Suppose we
were to interpret this procedure using normal-order evaluation, as discussed in
1.1.5. (The normal-order-evaluation rule for if is
described in Exercise 1.5.) Using the substitution method (for normal
order), illustrate the process generated in evaluating (gcd 206 40) and
indicate the remainder operations that are actually performed. How many
remainder operations are actually performed in the normal-order
evaluation of (gcd 206 40)? In the applicative-order evaluation?

@ -0,0 +1,4 @@
Exercise 1.21: Use the smallest-divisor
procedure to find the smallest divisor of each of the following numbers: 199,
1999, 19999.

@ -0,0 +1,67 @@
Exercise 1.22: Most Lisp implementations include
a primitive called runtime that returns an integer that specifies the
amount of time the system has been running (measured, for example, in
microseconds). The following timed-prime-test procedure, when called
with an integer
n
, prints
n
and checks to see if
n
is prime. If
n
is prime, the procedure prints three asterisks followed by the amount of
time used in performing the test.
(define (timed-prime-test n)
(newline)
(display n)
(start-prime-test n (runtime)))
(define (start-prime-test n start-time)
(if (prime? n)
(report-prime (- (runtime)
start-time))))
(define (report-prime elapsed-time)
(display " *** ")
(display elapsed-time))
Using this procedure, write a procedure search-for-primes that checks
the primality of consecutive odd integers in a specified range. Use your
procedure to find the three smallest primes larger than 1000; larger than
10,000; larger than 100,000; larger than 1,000,000. Note the time needed to
test each prime. Since the testing algorithm has order of growth of
Θ
(
n
)
, you should expect that testing for primes
around 10,000 should take about
10
times as long as testing for
primes around 1000. Do your timing data bear this out? How well do the data
for 100,000 and 1,000,000 support the
Θ
(
n
)
prediction? Is your
result compatible with the notion that programs on your machine run in time
proportional to the number of steps required for the computation?

@ -0,0 +1,16 @@
Exercise 1.23: The smallest-divisor
procedure shown at the start of this section does lots of needless testing:
After it checks to see if the number is divisible by 2 there is no point in
checking to see if it is divisible by any larger even numbers. This suggests
that the values used for test-divisor should not be 2, 3, 4, 5, 6,
…, but rather 2, 3, 5, 7, 9, …. To implement this change, define a
procedure next that returns 3 if its input is equal to 2 and otherwise
returns its input plus 2. Modify the smallest-divisor procedure to use
(next test-divisor) instead of (+ test-divisor 1). With
timed-prime-test incorporating this modified version of
smallest-divisor, run the test for each of the 12 primes found in
Exercise 1.22. Since this modification halves the number of test steps,
you should expect it to run about twice as fast. Is this expectation
confirmed? If not, what is the observed ratio of the speeds of the two
algorithms, and how do you explain the fact that it is different from 2?

@ -0,0 +1,17 @@
Exercise 1.24: Modify the
timed-prime-test procedure of Exercise 1.22 to use
fast-prime? (the Fermat method), and test each of the 12 primes you
found in that exercise. Since the Fermat test has
Θ
(
log
n
)
growth, how would you expect the time to test primes near 1,000,000 to
compare with the time needed to test primes near 1000? Do your data bear this
out? Can you explain any discrepancy you find?

@ -0,0 +1,11 @@
Exercise 1.25: Alyssa P. Hacker complains that
we went to a lot of extra work in writing expmod. After all, she says,
since we already know how to compute exponentials, we could have simply written
(define (expmod base exp m)
(remainder (fast-expt base exp) m))
Is she correct? Would this procedure serve as well for our fast prime tester?
Explain.

@ -0,0 +1,42 @@
Exercise 1.26: Louis Reasoner is having great
difficulty doing Exercise 1.24. His fast-prime? test seems to run
more slowly than his prime? test. Louis calls his friend Eva Lu Ator
over to help. When they examine Louis’s code, they find that he has rewritten
the expmod procedure to use an explicit multiplication, rather than
calling square:
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(remainder
(* (expmod base (/ exp 2) m)
(expmod base (/ exp 2) m))
m))
(else
(remainder
(* base
(expmod base (- exp 1) m))
m))))
“I don’t see what difference that could make,” says Louis. “I do.” says
Eva. “By writing the procedure like that, you have transformed the
Θ
(
log
n
)
process into a
Θ
(
n
)
process.”
Explain.

@ -0,0 +1,23 @@
Exercise 1.27: Demonstrate that the Carmichael
numbers listed in Footnote 47 really do fool the Fermat test. That is,
write a procedure that takes an integer
n
and tests whether
a
n
is
congruent to
a
modulo
n
for every
a
<
n
, and try your procedure
on the given Carmichael numbers.

@ -0,0 +1,92 @@
Exercise 1.28: One variant of the Fermat test
that cannot be fooled is called the
Miller-Rabin test (Miller 1976;
Rabin 1980). This starts from an alternate form of Fermat’s Little Theorem,
which states that if
n
is a prime number and
a
is any positive integer
less than
n
, then
a
raised to the
(
n
1
)
-st power is congruent to 1
modulo
n
. To test the primality of a number
n
by the Miller-Rabin
test, we pick a random number
a
<
n
and raise
a
to the
(
n
1
)
-st
power modulo
n
using the expmod procedure. However, whenever we
perform the squaring step in expmod, we check to see if we have
discovered a “nontrivial square root of 1 modulo
n
,” that is, a number
not equal to 1 or
n
1
whose square is equal to 1 modulo
n
. It is
possible to prove that if such a nontrivial square root of 1 exists, then
n
is not prime. It is also possible to prove that if
n
is an odd number that
is not prime, then, for at least half the numbers
a
<
n
, computing
a
n
1
in this way will reveal a nontrivial square root of 1 modulo
n
. (This is why the Miller-Rabin test cannot be fooled.) Modify the
expmod procedure to signal if it discovers a nontrivial square root of
1, and use this to implement the Miller-Rabin test with a procedure analogous
to fermat-test. Check your procedure by testing various known primes
and non-primes. Hint: One convenient way to make expmod signal is to
have it return 0.

@ -0,0 +1,149 @@
Exercise 1.29: Simpson’s Rule is a more accurate
method of numerical integration than the method illustrated above. Using
Simpson’s Rule, the integral of a function
f
between
a
and
b
is
approximated as
h
3
(
y
0
+
4
y
1
+
2
y
2
+
4
y
3
+
2
y
4
+
+
2
y
n
2
+
4
y
n
1
+
y
n
)
,
where
h
=
(
b
a
)
/
n
, for some even integer
n
, and
y
k
=
f
(
a
+
k
h
)
. (Increasing
n
increases the
accuracy of the approximation.) Define a procedure that takes as arguments
f
,
a
,
b
, and
n
and returns the value of the integral, computed
using Simpson’s Rule. Use your procedure to integrate cube between 0
and 1 (with
n
=
100
and
n
=
1000
), and compare the results to those of
the integral procedure shown above.

@ -0,0 +1,4 @@
Exercise 1.3: Define a procedure that takes three
numbers as arguments and returns the sum of the squares of the two larger
numbers.

@ -0,0 +1,13 @@
Exercise 1.30: The sum procedure above
generates a linear recursion. The procedure can be rewritten so that the sum
is performed iteratively. Show how to do this by filling in the missing
expressions in the following definition:
(define (sum term a next b)
(define (iter a result)
(if ⟨??⟩
⟨??⟩
(iter ⟨??⟩ ⟨??⟩)))
(iter ⟨??⟩ ⟨??⟩))

@ -0,0 +1,63 @@
Exercise 1.31:
The sum procedure is only the simplest of a vast number of similar
abstractions that can be captured as higher-order procedures.51 Write an analogous
procedure called product that returns the product of the values of a
function at points over a given range. Show how to define factorial in
terms of product. Also use product to compute approximations to
π
using the formula52
π
4
=
2
4
4
6
6
8
3
3
5
5
7
7
.
If your product procedure generates a recursive process, write one that
generates an iterative process. If it generates an iterative process, write
one that generates a recursive process.

@ -0,0 +1,25 @@
Exercise 1.32:
Show that sum and product (Exercise 1.31) are both special
cases of a still more general notion called accumulate that combines a
collection of terms, using some general accumulation function:
(accumulate
combiner null-value term a next b)
Accumulate takes as arguments the same term and range specifications as
sum and product, together with a combiner procedure (of
two arguments) that specifies how the current term is to be combined with the
accumulation of the preceding terms and a null-value that specifies what
base value to use when the terms run out. Write accumulate and show how
sum and product can both be defined as simple calls to
accumulate.
If your accumulate procedure generates a recursive process, write one
that generates an iterative process. If it generates an iterative process,
write one that generates a recursive process.

@ -0,0 +1,45 @@
Exercise 1.33: You can obtain an even more
general version of accumulate (Exercise 1.32) by introducing the
notion of a
filter on the terms to be combined. That is, combine
only those terms derived from values in the range that satisfy a specified
condition. The resulting filtered-accumulate abstraction takes the same
arguments as accumulate, together with an additional predicate of one argument
that specifies the filter. Write filtered-accumulate as a procedure.
Show how to express the following using filtered-accumulate:
the sum of the squares of the prime numbers in the interval
a
to
b
(assuming that you have a prime? predicate already written)
the product of all the positive integers less than
n
that are relatively
prime to
n
(i.e., all positive integers
i
<
n
such that
GCD
(
i
,
n
)
=
1
).

@ -0,0 +1,18 @@
Exercise 1.34: Suppose we define the procedure
(define (f g) (g 2))
Then we have
(f square)
4
(f (lambda (z) (* z (+ z 1))))
6
What happens if we (perversely) ask the interpreter to evaluate the combination
(f f)? Explain.

@ -0,0 +1,21 @@
Exercise 1.35: Show that the golden ratio
φ
(1.2.2) is a fixed point of the transformation
x
1
+
1
/
x
, and use this fact to compute
φ
by means
of the fixed-point procedure.

@ -0,0 +1,46 @@
Exercise 1.36: Modify fixed-point so that
it prints the sequence of approximations it generates, using the newline
and display primitives shown in Exercise 1.22. Then find a
solution to
x
x
=
1000
by finding a fixed point of
x
log
(
1000
)
/
log
(
x
)
. (Use Scheme’s primitive log
procedure, which computes natural logarithms.) Compare the number of steps
this takes with and without average damping. (Note that you cannot start
fixed-point with a guess of 1, as this would cause division by
log
(
1
)
=
0
.)

@ -0,0 +1,166 @@
Exercise 1.37:
An infinite
continued fraction is an expression of the form
f
=
N
1
D
1
+
N
2
D
2
+
N
3
D
3
+
.
As an example, one can show that the infinite continued fraction expansion with
the
N
i
and the
D
i
all equal to 1 produces
1
/
φ
, where
φ
is the golden ratio (described in 1.2.2). One way to
approximate an infinite continued fraction is to truncate the expansion after a
given number of terms. Such a truncation—a so-called
finite continued fraction
k-term
finite continued fraction—has the form
N
1
D
1
+
N
2
+
N
k
D
k
.
Suppose that n and d are procedures of one argument (the term
index
i
) that return the
N
i
and
D
i
of the terms of the
continued fraction. Define a procedure cont-frac such that evaluating
(cont-frac n d k) computes the value of the
k
-term finite continued
fraction. Check your procedure by approximating
1
/
φ
using
(cont-frac (lambda (i) 1.0)
(lambda (i) 1.0)
k)
for successive values of k. How large must you make k in order
to get an approximation that is accurate to 4 decimal places?
If your cont-frac procedure generates a recursive process, write one
that generates an iterative process. If it generates an iterative process,
write one that generates a recursive process.

@ -0,0 +1,28 @@
Exercise 1.38: In 1737, the Swiss mathematician
Leonhard Euler published a memoir De Fractionibus Continuis, which
included a continued fraction expansion for
e
2
, where
e
is the base
of the natural logarithms. In this fraction, the
N
i
are all 1, and
the
D
i
are successively 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, ….
Write a program that uses your cont-frac procedure from Exercise 1.37
to approximate
e
, based on Euler’s expansion.

@ -0,0 +1,53 @@
Exercise 1.39: A continued fraction
representation of the tangent function was published in 1770 by the German
mathematician J.H. Lambert:
tan
x
=
x
1
x
2
3
x
2
5
,
where
x
is in radians. Define a procedure (tan-cf x k) that
computes an approximation to the tangent function based on Lambert’s formula.
k specifies the number of terms to compute, as in Exercise 1.37.

@ -0,0 +1,8 @@
Exercise 1.4: Observe that our model of
evaluation allows for combinations whose operators are compound expressions.
Use this observation to describe the behavior of the following procedure:
(define (a-plus-abs-b a b)
((if (> b 0) + -) a b))

@ -0,0 +1,27 @@
Exercise 1.40: Define a procedure cubic
that can be used together with the newtons-method procedure in
expressions of the form
(newtons-method (cubic a b c) 1)
to approximate zeros of the cubic
x
3
+
a
x
2
+
b
x
+
c
.

@ -0,0 +1,9 @@
Exercise 1.41: Define a procedure double
that takes a procedure of one argument as argument and returns a procedure that
applies the original procedure twice. For example, if inc is a
procedure that adds 1 to its argument, then (double inc) should be a
procedure that adds 2. What value is returned by
(((double (double double)) inc) 5)

@ -0,0 +1,32 @@
Exercise 1.42: Let
f
and
g
be two
one-argument functions. The
composition
f
after
g
is defined
to be the function
x
f
(
g
(
x
)
)
. Define a procedure
compose that implements composition. For example, if inc is a
procedure that adds 1 to its argument,
((compose square inc) 6)
49

@ -0,0 +1,110 @@
Exercise 1.43: If
f
is a numerical function
and
n
is a positive integer, then we can form the
n
th
repeated
application of
f
, which is defined to be the function whose value at
x
is
f
(
f
(
(
f
(
x
)
)
)
)
. For example, if
f
is the
function
x
x
+
1
, then the
n
th
repeated application of
f
is
the function
x
x
+
n
. If
f
is the operation of squaring a
number, then the
n
th
repeated application of
f
is the function that
raises its argument to the
2
n
-th
power. Write a procedure that takes as
inputs a procedure that computes
f
and a positive integer
n
and returns
the procedure that computes the
n
th
repeated application of
f
. Your
procedure should be able to be used as follows:
((repeated square 2) 5)
625
Hint: You may find it convenient to use compose from Exercise 1.42.

@ -0,0 +1,56 @@
Exercise 1.44: The idea of
smoothing a
function is an important concept in signal processing. If
f
is a function
and
d
x
is some small number, then the smoothed version of
f
is the
function whose value at a point
x
is the average of
f
(
x
d
x
)
,
f
(
x
)
, and
f
(
x
+
d
x
)
. Write a procedure
smooth that takes as input a procedure that computes
f
and returns a
procedure that computes the smoothed
f
. It is sometimes valuable to
repeatedly smooth a function (that is, smooth the smoothed function, and so on)
to obtain the
n-fold smoothed function. Show how to generate
the n-fold smoothed function of any given function using smooth and
repeated from Exercise 1.43.

@ -0,0 +1,97 @@
Exercise 1.45: We saw in 1.3.3
that attempting to compute square roots by naively finding a fixed point of
y
x
/
y
does not converge, and that this can be fixed by average
damping. The same method works for finding cube roots as fixed points of the
average-damped
y
x
/
y
2
. Unfortunately, the process does not
work for fourth roots—a single average damp is not enough to make a
fixed-point search for
y
x
/
y
3
converge. On the other hand, if
we average damp twice (i.e., use the average damp of the average damp of
y
x
/
y
3
) the fixed-point search does converge. Do some experiments
to determine how many average damps are required to compute
n
th
roots as a
fixed-point search based upon repeated average damping of
y
x
/
y
n
1
.
Use this to implement a simple procedure for computing
n
th
roots using fixed-point, average-damp, and the
repeated procedure of Exercise 1.43. Assume that any arithmetic
operations you need are available as primitives.

@ -0,0 +1,15 @@
Exercise 1.46: Several of the numerical methods
described in this chapter are instances of an extremely general computational
strategy known as
iterative improvement. Iterative improvement says
that, to compute something, we start with an initial guess for the answer, test
if the guess is good enough, and otherwise improve the guess and continue the
process using the improved guess as the new guess. Write a procedure
iterative-improve that takes two procedures as arguments: a method for
telling whether a guess is good enough and a method for improving a guess.
Iterative-improve should return as its value a procedure that takes a
guess as argument and keeps improving the guess until it is good enough.
Rewrite the sqrt procedure of 1.1.7 and the
fixed-point procedure of 1.3.3 in terms of
iterative-improve.

@ -0,0 +1,26 @@
Exercise 1.5: Ben Bitdiddle has invented a test
to determine whether the interpreter he is faced with is using
applicative-order evaluation or normal-order evaluation. He defines the
following two procedures:
(define (p) (p))
(define (test x y)
(if (= x 0)
0
y))
Then he evaluates the expression
(test 0 (p))
What behavior will Ben observe with an interpreter that uses applicative-order
evaluation? What behavior will he observe with an interpreter that uses
normal-order evaluation? Explain your answer. (Assume that the evaluation
rule for the special form if is the same whether the interpreter is
using normal or applicative order: The predicate expression is evaluated first,
and the result determines whether to evaluate the consequent or the alternative
expression.)

@ -0,0 +1,34 @@
Exercise 1.6: Alyssa P. Hacker doesn’t see why
if needs to be provided as a special form. “Why can’t I just define it
as an ordinary procedure in terms of cond?” she asks. Alyssa’s friend
Eva Lu Ator claims this can indeed be done, and she defines a new version of
if:
(define (new-if predicate
then-clause
else-clause)
(cond (predicate then-clause)
(else else-clause)))
Eva demonstrates the program for Alyssa:
(new-if (= 2 3) 0 5)
5
(new-if (= 1 1) 0 5)
0
Delighted, Alyssa uses new-if to rewrite the square-root program:
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
What happens when Alyssa attempts to use this to compute square roots?
Explain.

@ -0,0 +1,11 @@
Exercise 1.7: The good-enough? test used
in computing square roots will not be very effective for finding the square
roots of very small numbers. Also, in real computers, arithmetic operations
are almost always performed with limited precision. This makes our test
inadequate for very large numbers. Explain these statements, with examples
showing how the test fails for small and large numbers. An alternative
strategy for implementing good-enough? is to watch how guess
changes from one iteration to the next and to stop when the change is a very
small fraction of the guess. Design a square-root procedure that uses this
kind of end test. Does this work better for small and large numbers?

@ -0,0 +1,37 @@
Exercise 1.8: Newton’s method for cube roots is
based on the fact that if
y
is an approximation to the cube root of
x
,
then a better approximation is given by the value
x
/
y
2
+
2
y
3
.
Use this formula to implement a cube-root procedure analogous to the
square-root procedure. (In 1.3.4 we will see how to implement
Newton’s method in general as an abstraction of these square-root and cube-root
procedures.)

@ -0,0 +1,20 @@
Exercise 1.9: Each of the following two
procedures defines a method for adding two positive integers in terms of the
procedures inc, which increments its argument by 1, and dec,
which decrements its argument by 1.
(define (+ a b)
(if (= a 0)
b
(inc (+ (dec a) b))))
(define (+ a b)
(if (= a 0)
b
(+ (dec a) (inc b))))
Using the substitution model, illustrate the process generated by each
procedure in evaluating (+ 4 5). Are these processes iterative or
recursive?

@ -0,0 +1,6 @@
Exercise 2.1: Define a better version of
make-rat that handles both positive and negative arguments.
Make-rat should normalize the sign so that if the rational number is
positive, both the numerator and denominator are positive, and if the rational
number is negative, only the numerator is negative.

@ -0,0 +1,5 @@
Exercise 2.10: Ben Bitdiddle, an expert systems
programmer, looks over Alyssa’s shoulder and comments that it is not clear what
it means to divide by an interval that spans zero. Modify Alyssa’s code to
check for this condition and to signal an error if it occurs.

@ -0,0 +1,35 @@
Exercise 2.11: In passing, Ben also cryptically
comments: “By testing the signs of the endpoints of the intervals, it is
possible to break mul-interval into nine cases, only one of which
requires more than two multiplications.” Rewrite this procedure using Ben’s
suggestion.
After debugging her program, Alyssa shows it to a potential user, who complains
that her program solves the wrong problem. He wants a program that can deal
with numbers represented as a center value and an additive tolerance; for
example, he wants to work with intervals such as 3.5
±
0.15 rather than
[3.35, 3.65]. Alyssa returns to her desk and fixes this problem by supplying
an alternate constructor and alternate selectors:
(define (make-center-width c w)
(make-interval (- c w) (+ c w)))
(define (center i)
(/ (+ (lower-bound i)
(upper-bound i))
2))
(define (width i)
(/ (- (upper-bound i)
(lower-bound i))
2))
Unfortunately, most of Alyssa’s users are engineers. Real engineering
situations usually involve measurements with only a small uncertainty, measured
as the ratio of the width of the interval to the midpoint of the interval.
Engineers usually specify percentage tolerances on the parameters of devices,
as in the resistor specifications given earlier.

@ -0,0 +1,6 @@
Exercise 2.12: Define a constructor
make-center-percent that takes a center and a percentage tolerance and
produces the desired interval. You must also define a selector percent
that produces the percentage tolerance for a given interval. The center
selector is the same as the one shown above.

@ -0,0 +1,88 @@
Exercise 2.13: Show that under the assumption of
small percentage tolerances there is a simple formula for the approximate
percentage tolerance of the product of two intervals in terms of the tolerances
of the factors. You may simplify the problem by assuming that all numbers are
positive.
After considerable work, Alyssa P. Hacker delivers her finished system.
Several years later, after she has forgotten all about it, she gets a frenzied
call from an irate user, Lem E. Tweakit. It seems that Lem has noticed that
the formula for parallel resistors can be written in two algebraically
equivalent ways:
R
1
R
2
R
1
+
R
2
and
1
1
/
R
1
+
1
/
R
2
.
He has written the following two programs, each of which computes the
parallel-resistors formula differently:
(define (par1 r1 r2)
(div-interval
(mul-interval r1 r2)
(add-interval r1 r2)))
(define (par2 r1 r2)
(let ((one (make-interval 1 1)))
(div-interval
one
(add-interval
(div-interval one r1)
(div-interval one r2)))))
Lem complains that Alyssa’s program gives different answers for the two ways of
computing. This is a serious complaint.

@ -0,0 +1,27 @@
Exercise 2.14: Demonstrate that Lem is right.
Investigate the behavior of the system on a variety of arithmetic
expressions. Make some intervals
A
and
B
, and use them in computing the
expressions
A
/
A
and
A
/
B
. You will get the most insight by
using intervals whose width is a small percentage of the center value. Examine
the results of the computation in center-percent form (see Exercise 2.12).

@ -0,0 +1,8 @@
Exercise 2.15: Eva Lu Ator, another user, has
also noticed the different intervals computed by different but algebraically
equivalent expressions. She says that a formula to compute with intervals using
Alyssa’s system will produce tighter error bounds if it can be written in such
a form that no variable that represents an uncertain number is repeated. Thus,
she says, par2 is a “better” program for parallel resistances than
par1. Is she right? Why?

@ -0,0 +1,5 @@
Exercise 2.16: Explain, in general, why
equivalent algebraic expressions may lead to different answers. Can you devise
an interval-arithmetic package that does not have this shortcoming, or is this
task impossible? (Warning: This problem is very difficult.)

@ -0,0 +1,9 @@
Exercise 2.17: Define a procedure
last-pair that returns the list that contains only the last element of a
given (nonempty) list:
(last-pair (list 23 72 149 34))
(34)

@ -0,0 +1,9 @@
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)

@ -0,0 +1,54 @@
Exercise 2.19: Consider the change-counting
program of 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:
(define us-coins
(list 50 25 10 5 1))
(define uk-coins
(list 100 50 20 10 5 2 1 0.5))
We could then call cc as follows:
(cc 100 us-coins)
292
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:
(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)))))
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?

@ -0,0 +1,26 @@
Exercise 2.2: Consider the problem of
representing line segments in a plane. Each segment is represented as a pair
of points: a starting point and an ending point. Define a constructor
make-segment and selectors start-segment and end-segment
that define the representation of segments in terms of points. Furthermore, a
point can be represented as a pair of numbers: the
x
coordinate and the
y
coordinate. Accordingly, specify a constructor make-point and
selectors x-point and y-point that define this representation.
Finally, using your selectors and constructors, define a procedure
midpoint-segment that takes a line segment as argument and returns its
midpoint (the point whose coordinates are the average of the coordinates of the
endpoints). To try your procedures, you’ll need a way to print points:
(define (print-point p)
(newline)
(display "(")
(display (x-point p))
(display ",")
(display (y-point p))
(display ")"))

@ -0,0 +1,47 @@
Exercise 2.20: The procedures +,
*, and list take arbitrary numbers of arguments. One way to
define such procedures is to use define with
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
(define (f x y . z) ⟨body⟩)
the procedure f can be called with two or more arguments. If we
evaluate
(f 1 2 3 4 5 6)
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
(define (g . w) ⟨body⟩)
the procedure g can be called with zero or more arguments. If we
evaluate
(g 1 2 3 4 5 6)
then in the body of g, w will be the list (1 2 3 4 5
6).77
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,
(same-parity 1 2 3 4 5 6 7)
(1 3 5 7)
(same-parity 2 3 4 5 6 7)
(2 4 6)

@ -0,0 +1,21 @@
Exercise 2.21: The procedure square-list
takes a list of numbers as argument and returns a list of the squares of those
numbers.
(square-list (list 1 2 3 4))
(1 4 9 16)
Here are two different definitions of square-list. Complete both of
them by filling in the missing expressions:
(define (square-list items)
(if (null? items)
nil
(cons ⟨??⟩ ⟨??⟩)))
(define (square-list items)
(map ⟨??⟩ ⟨??⟩))

@ -0,0 +1,32 @@
Exercise 2.22: Louis Reasoner tries to rewrite
the first square-list procedure of Exercise 2.21 so that it
evolves an iterative process:
(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(cons (square (car things))
answer))))
(iter items nil))
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:
(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(cons answer
(square
(car things))))))
(iter items nil))
This doesn’t work either. Explain.

@ -0,0 +1,22 @@
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,
(for-each
(lambda (x) (newline) (display x))
(list 57 321 88))
57
321
88
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.

@ -0,0 +1,5 @@
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 Figure 2.6).

@ -0,0 +1,8 @@
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))))))

@ -0,0 +1,15 @@
Exercise 2.26: Suppose we define x and
y to be two lists:
(define x (list 1 2 3))
(define y (list 4 5 6))
What result is printed by the interpreter in response to evaluating each of the
following expressions:
(append x y)
(cons x y)
(list x y)

@ -0,0 +1,19 @@
Exercise 2.27: Modify your reverse
procedure of 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,
(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))

@ -0,0 +1,16 @@
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,
(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)

@ -0,0 +1,48 @@
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):
(define (make-mobile left right)
(list left right))
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:
(define (make-branch length structure)
(list length structure))
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.
Using your selectors, define a procedure total-weight that returns the
total weight of a mobile.
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.
Suppose we change the representation of mobiles so that the constructors are
(define (make-mobile left right)
(cons left right))
(define (make-branch length structure)
(cons length structure))
How much do you need to change your programs to convert to the new
representation?

@ -0,0 +1,8 @@
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
using either representation?

@ -0,0 +1,15 @@
Exercise 2.30: Define a procedure
square-tree analogous to the square-list procedure of
Exercise 2.21. That is, square-tree should behave as follows:
(square-tree
(list 1
(list 2 (list 3 4) 5)
(list 6 7)))
(1 (4 (9 16) 25) (36 49))
Define square-tree both directly (i.e., without using any higher-order
procedures) and also by using map and recursion.

@ -0,0 +1,8 @@
Exercise 2.31: Abstract your answer to
Exercise 2.30 to produce a procedure tree-map with the property
that square-tree could be defined as
(define (square-tree tree)
(tree-map square tree))

@ -0,0 +1,14 @@
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:
(define (subsets s)
(if (null? s)
(list nil)
(let ((rest (subsets (cdr s))))
(append rest (map ⟨??⟩ rest)))))

@ -0,0 +1,15 @@
Exercise 2.33: Fill in the missing expressions
to complete the following definitions of some basic list-manipulation
operations as accumulations:
(define (map p sequence)
(accumulate (lambda (x y) ⟨??⟩)
nil sequence))
(define (append seq1 seq2)
(accumulate cons ⟨??⟩ ⟨??⟩))
(define (length sequence)
(accumulate ⟨??⟩ 0 sequence))

@ -0,0 +1,182 @@
Exercise 2.34: Evaluating a polynomial in
x
at a given value of
x
can be formulated as an accumulation. We evaluate
the polynomial
a
n
x
n
+
a
n
1
x
n
1
+
+
a
1
x
+
a
0
using a well-known algorithm called
Horner’s rule, which structures
the computation as
(
(
a
n
x
+
a
n
1
)
x
+
+
a
1
)
x
+
a
0
.
In other words, we start with
a
n
, multiply by
x
, add
a
n
1
, multiply by
x
, and so on, until we reach
a
0
.82
Fill in the following template to produce a procedure that evaluates a
polynomial using Horner’s rule. Assume that the coefficients of the polynomial
are arranged in a sequence, from
a
0
through
a
n
.
(define
(horner-eval x coefficient-sequence)
(accumulate
(lambda (this-coeff higher-terms)
⟨??⟩)
0
coefficient-sequence))
For example, to compute
1
+
3
x
+
5
x
3
+
x
5
at
x
=
2
you
would evaluate
(horner-eval 2 (list 1 3 0 5 0 1))

@ -0,0 +1,7 @@
Exercise 2.35: Redefine count-leaves from
2.2.2 as an accumulation:
(define (count-leaves t)
(accumulate ⟨??⟩ ⟨??⟩ (map ⟨??⟩ ⟨??⟩)))

@ -0,0 +1,18 @@
Exercise 2.36: The procedure accumulate-n
is similar to accumulate except that it takes as its third argument a
sequence of sequences, which are all assumed to have the same number of
elements. It applies the designated accumulation procedure to combine all the
first elements of the sequences, all the second elements of the sequences, and
so on, and returns a sequence of the results. For instance, if s is a
sequence containing four sequences, ((1 2 3) (4 5 6) (7 8 9) (10 11
12)), then the value of (accumulate-n + 0 s) should be the sequence
(22 26 30). Fill in the missing expressions in the following definition
of accumulate-n:
(define (accumulate-n op init seqs)
(if (null? (car seqs))
nil
(cons (accumulate op init ⟨??⟩)
(accumulate-n op init ⟨??⟩))))

@ -0,0 +1,250 @@
Exercise 2.37:
Suppose we represent vectors v =
(
v
i
)
as sequences of numbers, and
matrices m =
(
m
i
j
)
as sequences of vectors (the rows of the
matrix). For example, the matrix
(
1
2
3
4
4
5
6
6
6
7
8
9
)
is represented as the sequence ((1 2 3 4) (4 5 6 6) (6 7 8 9)). With
this representation, we can use sequence operations to concisely express the
basic matrix and vector operations. These operations (which are described in
any book on matrix algebra) are the following:
(dot-product v w)
returns the sum
Σ
i
v
i
w
i
;
(matrix-*-vector m v)
returns the vector
t
,
where
t
i
=
Σ
j
m
i
j
v
j
;
(matrix-*-matrix m n)
returns the matrix
p
,
where
p
i
j
=
Σ
k
m
i
k
n
k
j
;
(transpose m)
returns the matrix
n
,
where
n
i
j
=
m
j
i
.
We can define the dot product as83
(define (dot-product v w)
(accumulate + 0 (map * v w)))
Fill in the missing expressions in the following procedures for computing the
other matrix operations. (The procedure accumulate-n is defined in
Exercise 2.36.)
(define (matrix-*-vector m v)
(map ⟨??⟩ m))
(define (transpose mat)
(accumulate-n ⟨??⟩ ⟨??⟩ mat))
(define (matrix-*-matrix m n)
(let ((cols (transpose n)))
(map ⟨??⟩ m)))

@ -0,0 +1,27 @@
Exercise 2.38: The accumulate procedure
is also known as fold-right, because it combines the first element of
the sequence with the result of combining all the elements to the right. There
is also a fold-left, which is similar to fold-right, except that
it combines elements working in the opposite direction:
(define (fold-left op initial sequence)
(define (iter result rest)
(if (null? rest)
result
(iter (op result (car rest))
(cdr rest))))
(iter initial sequence))
What are the values of
(fold-right / 1 (list 1 2 3))
(fold-left / 1 (list 1 2 3))
(fold-right list nil (list 1 2 3))
(fold-left list nil (list 1 2 3))
Give a property that op should satisfy to guarantee that
fold-right and fold-left will produce the same values for any
sequence.

@ -0,0 +1,13 @@
Exercise 2.39: Complete the following
definitions of reverse (Exercise 2.18) in terms of
fold-right and fold-left from Exercise 2.38:
(define (reverse sequence)
(fold-right
(lambda (x y) ⟨??⟩) nil sequence))
(define (reverse sequence)
(fold-left
(lambda (x y) ⟨??⟩) nil sequence))

@ -0,0 +1,14 @@
Exercise 2.4: Here is an alternative procedural
representation of pairs. For this representation, verify that (car (cons
x y)) yields x for any objects x and y.
(define (cons x y)
(lambda (m) (m x y)))
(define (car z)
(z (lambda (p q) p)))
What is the corresponding definition of cdr? (Hint: To verify that this
works, make use of the substitution model of 1.1.5.)

@ -0,0 +1,27 @@
Exercise 2.40: Define a procedure
unique-pairs that, given an integer
n
, generates the sequence of
pairs
(
i
,
j
)
with
1
j
<
i
n
. Use unique-pairs
to simplify the definition of prime-sum-pairs given above.

@ -0,0 +1,14 @@
Exercise 2.41: Write a procedure to find all
ordered triples of distinct positive integers
i
,
j
, and
k
less than
or equal to a given integer
n
that sum to a given integer
s
.

@ -0,0 +1,142 @@
Exercise 2.42: The “eight-queens puzzle” asks
how to place eight queens on a chessboard so that no queen is in check from any
other (i.e., no two queens are in the same row, column, or diagonal). One
possible solution is shown in Figure 2.8. One way to solve the puzzle is
to work across the board, placing a queen in each column. Once we have placed
k
1
queens, we must place the
k
th
queen in a position where it does
not check any of the queens already on the board. We can formulate this
approach recursively: Assume that we have already generated the sequence of all
possible ways to place
k
1
queens in the first
k
1
columns of the
board. For each of these ways, generate an extended set of positions by
placing a queen in each row of the
k
th
column. Now filter these, keeping
only the positions for which the queen in the
k
th
column is safe with
respect to the other queens. This produces the sequence of all ways to place
k
queens in the first
k
columns. By continuing this process, we will
produce not only one solution, but all solutions to the puzzle.
SVG
Figure 2.8: A solution to the eight-queens puzzle.
We implement this solution as a procedure queens, which returns a
sequence of all solutions to the problem of placing
n
queens on an
n
×
n
chessboard. Queens has an internal procedure
queen-cols that returns the sequence of all ways to place queens in the
first
k
columns of the board.
(define (queens board-size)
(define (queen-cols k)
(if (= k 0)
(list empty-board)
(filter
(lambda (positions)
(safe? k positions))
(flatmap
(lambda (rest-of-queens)
(map (lambda (new-row)
(adjoin-position
new-row
k
rest-of-queens))
(enumerate-interval
1
board-size)))
(queen-cols (- k 1))))))
(queen-cols board-size))
In this procedure rest-of-queens is a way to place
k
1
queens in
the first
k
1
columns, and new-row is a proposed row in which to
place the queen for the
k
th
column. Complete the program by implementing
the representation for sets of board positions, including the procedure
adjoin-position, which adjoins a new row-column position to a set of
positions, and empty-board, which represents an empty set of positions.
You must also write the procedure safe?, which determines for a set of
positions, whether the queen in the
k
th
column is safe with respect to the
others. (Note that we need only check whether the new queen is safe—the
other queens are already guaranteed safe with respect to each other.)

@ -0,0 +1,28 @@
Exercise 2.43: Louis Reasoner is having a
terrible time doing Exercise 2.42. His queens procedure seems to
work, but it runs extremely slowly. (Louis never does manage to wait long
enough for it to solve even the
6
×
6
case.) When Louis asks Eva Lu Ator for
help, she points out that he has interchanged the order of the nested mappings
in the flatmap, writing it as
(flatmap
(lambda (new-row)
(map (lambda (rest-of-queens)
(adjoin-position
new-row k rest-of-queens))
(queen-cols (- k 1))))
(enumerate-interval 1 board-size))
Explain why this interchange makes the program run slowly. Estimate how long
it will take Louis’s program to solve the eight-queens puzzle, assuming that
the program in Exercise 2.42 solves the puzzle in time
T
.

@ -0,0 +1,5 @@
Exercise 2.44: Define the procedure
up-split used by corner-split. It is similar to
right-split, except that it switches the roles of below and
beside.

@ -0,0 +1,11 @@
Exercise 2.45: Right-split and
up-split can be expressed as instances of a general splitting operation.
Define a procedure split with the property that evaluating
(define right-split (split beside below))
(define up-split (split below beside))
produces procedures right-split and up-split with the same
behaviors as the ones already defined.

@ -0,0 +1,151 @@
Exercise 2.46: A two-dimensional vector
v
running from the origin to a point can be represented as a pair consisting of
an
x
-coordinate and a
y
-coordinate. Implement a data abstraction for
vectors by giving a constructor make-vect and corresponding selectors
xcor-vect and ycor-vect. In terms of your selectors and
constructor, implement procedures add-vect, sub-vect, and
scale-vect that perform the operations vector addition, vector
subtraction, and multiplying a vector by a scalar:
(
x
1
,
y
1
)
+
(
x
2
,
y
2
)
=
(
x
1
+
x
2
,
y
1
+
y
2
)
,
(
x
1
,
y
1
)
(
x
2
,
y
2
)
=
(
x
1
x
2
,
y
1
y
2
)
,
s
(
x
,
y
)
=
(
s
x
,
s
y
)
.

@ -0,0 +1,13 @@
Exercise 2.47: Here are two possible
constructors for frames:
(define (make-frame origin edge1 edge2)
(list origin edge1 edge2))
(define (make-frame origin edge1 edge2)
(cons origin (cons edge1 edge2)))
For each constructor supply the appropriate selectors to produce an
implementation for frames.

@ -0,0 +1,7 @@
Exercise 2.48: A directed line segment in the
plane can be represented as a pair of vectors—the vector running from the
origin to the start-point of the segment, and the vector running from the
origin to the end-point of the segment. Use your vector representation from
Exercise 2.46 to define a representation for segments with a constructor
make-segment and selectors start-segment and end-segment.

@ -0,0 +1,15 @@
Exercise 2.49: Use segments->painter
to define the following primitive painters:
The painter that draws the outline of the designated frame.
The painter that draws an “X” by connecting opposite corners of the frame.
The painter that draws a diamond shape by connecting the midpoints of the sides
of the frame.
The wave painter.

@ -0,0 +1,21 @@
Exercise 2.5: Show that we can represent pairs of
nonnegative integers using only numbers and arithmetic operations if we
represent the pair
a
and
b
as the integer that is the product
2
a
3
b
.
Give the corresponding definitions of the procedures cons,
car, and cdr.

@ -0,0 +1,4 @@
Exercise 2.50: Define the transformation
flip-horiz, which flips painters horizontally, and transformations that
rotate painters counterclockwise by 180 degrees and 270 degrees.

@ -0,0 +1,8 @@
Exercise 2.51: Define the below operation
for painters. Below takes two painters as arguments. The resulting
painter, given a frame, draws with the first painter in the bottom of the frame
and with the second painter in the top. Define below in two different
ways—first by writing a procedure that is analogous to the beside
procedure given above, and again in terms of beside and suitable
rotation operations (from Exercise 2.50).

@ -0,0 +1,18 @@
Exercise 2.52: Make changes to the square limit
of wave shown in Figure 2.9 by working at each of the levels
described above. In particular:
Add some segments to the primitive wave painter of Exercise 2.49
(to add a smile, for example).
Change the pattern constructed by corner-split (for example, by using
only one copy of the up-split and right-split images instead of
two).
Modify the version of square-limit that uses square-of-four so as
to assemble the corners in a different pattern. (For example, you might make
the big Mr. Rogers look outward from each corner of the square.)

@ -0,0 +1,12 @@
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))

@ -0,0 +1,21 @@
Exercise 2.54: Two lists are said to be
equal? if they contain equal elements arranged in the same order. For
example,
(equal? '(this is a list)
'(this is a list))
is true, but
(equal? '(this is a list)
'(this (is a) list))
is false. To be more precise, we can define equal? recursively in
terms of the basic eq? equality of symbols by saying that a and
b are equal? if they are both symbols and the symbols are
eq?, or if they are both lists such that (car a) is equal?
to (car b) and (cdr a) is equal? to (cdr b). Using
this idea, implement equal? as a procedure.102

@ -0,0 +1,8 @@
Exercise 2.55: Eva Lu Ator types to the
interpreter the expression
(car ''abracadabra)
To her surprise, the interpreter prints back quote. Explain.

@ -0,0 +1,59 @@
Exercise 2.56: Show how to extend the basic
differentiator to handle more kinds of expressions. For instance, implement
the differentiation rule
d
(
u
n
)
d
x
=
n
u
n
1
d
u
d
x
by adding a new clause to the deriv program and defining appropriate
procedures exponentiation?, base, exponent, and
make-exponentiation. (You may use the symbol ** to denote
exponentiation.) Build in the rules that anything raised to the power 0 is 1
and anything raised to the power 1 is the thing itself.

@ -0,0 +1,12 @@
Exercise 2.57: Extend the differentiation
program to handle sums and products of arbitrary numbers of (two or more)
terms. Then the last example above could be expressed as
(deriv '(* x y (+ x 3)) 'x)
Try to do this by changing only the representation for sums and products,
without changing the deriv procedure at all. For example, the
addend of a sum would be the first term, and the augend would be
the sum of the rest of the terms.

@ -0,0 +1,22 @@
Exercise 2.58: Suppose we want to modify the
differentiation program so that it works with ordinary mathematical notation,
in which + and * are infix rather than prefix operators. Since
the differentiation program is defined in terms of abstract data, we can modify
it to work with different representations of expressions solely by changing the
predicates, selectors, and constructors that define the representation of the
algebraic expressions on which the differentiator is to operate.
Show how to do this in order to differentiate algebraic expressions presented
in infix form, such as (x + (3 * (x + (y + 2)))). To simplify the task,
assume that + and * always take two arguments and that
expressions are fully parenthesized.
The problem becomes substantially harder if we allow standard algebraic
notation, such as (x + 3 * (x + y + 2)), which drops unnecessary
parentheses and assumes that multiplication is done before addition. Can you
design appropriate predicates, selectors, and constructors for this notation
such that our derivative program still works?

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save