mirror of
https://github.com/correl/sicp.git
synced 2024-11-23 19:19:56 +00:00
244 lines
7.6 KiB
Scheme
244 lines
7.6 KiB
Scheme
|
;; ====================================================================
|
||
|
;; SICP - 1.1: The Elements of Programming
|
||
|
;; ====================================================================
|
||
|
|
||
|
(define (square x)
|
||
|
(* x x))
|
||
|
|
||
|
|
||
|
(define (sum-of-squares a b)
|
||
|
(+ (square a) (square b)))
|
||
|
|
||
|
;; (define (abs x)
|
||
|
;; (cond ((< x 0) (- x))
|
||
|
;; ((= x 0) 0)
|
||
|
;; ((> x 0) x)))
|
||
|
|
||
|
(define (abs x)
|
||
|
(if (< x 0) (- x)
|
||
|
x))
|
||
|
|
||
|
(define (average x y)
|
||
|
(/ (+ x y) 2))
|
||
|
|
||
|
(define (sqrt x)
|
||
|
(define (sqrt-iter guess x)
|
||
|
(if (good-enough? guess x)
|
||
|
guess
|
||
|
(sqrt-iter (improve guess x)
|
||
|
x)))
|
||
|
|
||
|
(define (improve guess x)
|
||
|
(average guess (/ x guess)))
|
||
|
|
||
|
(define (good-enough? guess x)
|
||
|
(< (abs (- (square guess) x)) 0.001))
|
||
|
|
||
|
(sqrt-iter 1.0 x))
|
||
|
|
||
|
|
||
|
;; ====================================================================
|
||
|
;; *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
|
||
|
;; 10
|
||
|
|
||
|
(+ 5 3 4)
|
||
|
;; 12
|
||
|
|
||
|
(- 9 1)
|
||
|
;; 8
|
||
|
|
||
|
(/ 6 2)
|
||
|
;; 3
|
||
|
|
||
|
(+ (* 2 4) (- 4 6))
|
||
|
;; 10
|
||
|
|
||
|
(define a 3)
|
||
|
;; 3
|
||
|
|
||
|
(define b (+ a 1))
|
||
|
;; 4
|
||
|
|
||
|
(+ a b (* a b))
|
||
|
;; 19
|
||
|
|
||
|
(= a b)
|
||
|
;; #f
|
||
|
|
||
|
(if (and (> b a) (< b (* a b)))
|
||
|
b
|
||
|
a)
|
||
|
;; 4
|
||
|
|
||
|
(cond ((= a 4) 6)
|
||
|
((= b 4) (+ 6 7 a))
|
||
|
(else 25))
|
||
|
;; 16
|
||
|
|
||
|
(+ 2 (if (> b a) b a))
|
||
|
;; 6
|
||
|
|
||
|
(* (cond ((> a b) a)
|
||
|
((< a b) b)
|
||
|
(else -1))
|
||
|
(+ a 1))
|
||
|
;; 16
|
||
|
|
||
|
;; ===================================================================
|
||
|
;; *Exercise 1.2:* Translate the following expression into prefix
|
||
|
;; form.
|
||
|
;;
|
||
|
;; 5 + 4 + (2 - (3 - (6 + 4/5)))
|
||
|
;; -----------------------------
|
||
|
;; 3(6 - 2)(2 - 7)
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define ex1.2
|
||
|
(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5)))))
|
||
|
(* 3 (- 6 2) (- 2 7))))
|
||
|
|
||
|
;; ===================================================================
|
||
|
;; *Exercise 1.3:* Define a procedure that takes three numbers as
|
||
|
;; arguments and returns the sum of the squares of the two larger
|
||
|
;; numbers.
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
(define (ex1.3 a b c)
|
||
|
(cond ((and (> b a) (> c a)) (sum-of-squares b c))
|
||
|
((and (> a b) (> c b)) (sum-of-squares a c))
|
||
|
(#t (sum-of-squares a b))))
|
||
|
|
||
|
(define (ex1.3-fancy a b c)
|
||
|
(let* ((sorted (sort (list a b c) >))
|
||
|
(x (car sorted))
|
||
|
(y (cadr sorted)))
|
||
|
(+ (square x) (square y))))
|
||
|
|
||
|
;; ===================================================================
|
||
|
;; *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))
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
;; When the function is called, the following will happen:
|
||
|
;;
|
||
|
;; * The first expression in the list, (if (> b 0) + -) will be
|
||
|
;; evaluated. Within it, (> b 0) will be evaluated first, and
|
||
|
;; based on the value of b, the result of the evaluation will be +
|
||
|
;; or -.
|
||
|
;; * The remaining expressions (a and b) will be evaluated to their
|
||
|
;; passed-in values.
|
||
|
;; * The resulting expression will be evaluated, e.g. (+ 3 2)
|
||
|
;; * The final result will be the result of applying the + or -
|
||
|
;; operator to the operands a and b
|
||
|
|
||
|
;; ===================================================================
|
||
|
;; *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.)
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
;; Applicative order evaluation will evaluate test, 0 and (p), then
|
||
|
;; evaluate the application of the operator test on its
|
||
|
;; operands. However, attempting to evaluate (p) will hang, as it is a
|
||
|
;; recursive function that never exits.
|
||
|
;;
|
||
|
;; Normal order evaluation will first apply the operator test on its
|
||
|
;; operands, which will then evaluate 0 in the if statment. The
|
||
|
;; conditional expression will succeed, and so the function will
|
||
|
;; return 0, never evaluating (p).
|
||
|
|
||
|
;; ===================================================================
|
||
|
;; *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.
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
;; Calls to sqrt-iter will recurse indefinitely. This is because both
|
||
|
;; the then-clause and the else-clause passed to new-if will be
|
||
|
;; evaluated before the function new-if is applied.
|
||
|
|
||
|
;; ===================================================================
|
||
|
;; *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?
|
||
|
;; -------------------------------------------------------------------
|
||
|
|
||
|
;; ===================================================================
|
||
|
;; *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 + 2y
|
||
|
;; ----------
|
||
|
;; 3
|
||
|
;;
|
||
|
;; Use this formula to implement a cube-root procedure analogous to
|
||
|
;; the square-root procedure. (In section *Note 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.)
|
||
|
;; -------------------------------------------------------------------
|