Chapter 1

Exercise 1.1

The Question

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))

The Answer

We'll break this into chunks of each top-level expression. This will help us examine each expression in enough detail (though mainly to print each expression's result).

Exercise 1.2

The Question

Translate the following into prefix form:

\[ \frac{5 + 4 + (2 - (3 - (6 + \frac{4}{5}))}{3(6 - 2)(2 - 7)} \]

The Answer

We can translate this by recursively grouping values by the outermost common operation. This means we start with the fraction, and divide the numerator and denominator. Then we add for the numerator and multiply for the denominator and so on and so forth. Going through with this exercise, we finally come up with:

Exercise 1.3

The Question

Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.

The Answer

Prerequisites

Since we need to square twice, we'll first define the procedure square

(define (square x)
  (* x x))

(square 7)
49

As well as max to find the max of two numbers:

(define (max a b)
  (if (> a b) a b))

Testing max:

Exercise 1.4

The Question

Observe that our model of evaluation allows for combinations whose operators are compound expressions. Use this observation to describe the behaviour of the following procedure:

(define (a-plus-abs-b a b)
  ((if (> b 0) + -) a b))

The Answer

Adding a positive number and subtracting a negative number has the same effect as adding the absolute value of a number. We are able to change the procedure as observed. Thus + is returned as the procedure if b is greater than 0, and - otherwise.

Exercise 1.5

The Question

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 behaviour will Ben observe with an interpreter that uses applicative-order evaluation? What behaviour 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.)

Exercise 1.6

The Question

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:

Exercise 1.7

The Question

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?

Exercise 1.8

The Question

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 \[\frac{x/y^2 + 2y}{3}\] Use this formula to implement a cube-root procedure analogous to the square-root procedure.

The Answer

This exercise essentially requires us to rewrite the improve implementation from the previous exercise for cube roots:

Exercise 1.9

The Question

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?

Exercise 1.10

The Question

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 \(5n^2\) .

Exercise 1.11

The Question

A function \(f\) is defined by the rule that

\[f(n) = \begin{cases} n & \text{if n < 3} \\ f(n - 1) + 2f(n - 2) + 3f(n - 3) & \text{if n} \ge 3 \\ \end{cases}\]

Write a procedure that computes \(f\) by means of a recursive process. Write a procedure that computes \(f\) by means of an iterative process.

The Answer

Recursive Implementation

The rule directly spells out our recursive implementation:

Exercise 1.12

The Question

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. Write a procedure that computes elements of Pascal's triangle by means of a recursive process.