sicp/1-1.org
2014-05-19 01:42:59 -04:00

279 lines
7.9 KiB
Org Mode

#+BEGIN_HTML
---
title: 1.1 - The Elements of Programming
layout: org
---
#+END_HTML
* Code
#+BEGIN_SRC scheme :tangle yes
(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))
#+END_SRC
* Exercises
** 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 whichit is presented.
#+BEGIN_SRC scheme
;; -------------------------------------------------------------------
;; Exercise 1.1
;; -------------------------------------------------------------------
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
#+END_SRC
** Exercise 1.2
Translate the following expression into prefix form.
#+BEGIN_EXAMPLE
5 + 4 + (2 - (3 - (6 + 4/5)))
-----------------------------
3(6 - 2)(2 - 7)
#+END_EXAMPLE
#+BEGIN_SRC scheme :tangle yes
;; -------------------------------------------------------------------
;; Exercise 1.2
;; -------------------------------------------------------------------
(define ex1.2
(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5)))))
(* 3 (- 6 2) (- 2 7))))
#+END_SRC
** Exercise 1.3
Define a procedure that takes three numbers as arguments and
returns the sum of the squares of the two larger numbers.
#+BEGIN_SRC scheme :tangle yes
;; -------------------------------------------------------------------
;; Exercise 1.3
;; -------------------------------------------------------------------
(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))))
#+END_SRC
** 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:
#+BEGIN_SRC scheme
(define (a-plus-abs-b a b)
((if (> b 0) + -) a b))
#+END_SRC
-------------------------------------------------------------------
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:
#+BEGIN_SRC scheme
(define (p) (p))
(define (test x y)
(if (= x 0)
0
y))
#+END_SRC
Then he evaluates the expression
#+BEGIN_SRC scheme
(test 0 (p))
#+END_SRC
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':
#+BEGIN_SRC scheme
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
#+END_SRC
Eva demonstrates the program for Alyssa:
#+BEGIN_SRC scheme
(new-if (= 2 3) 0 5)
5
(new-if (= 1 1) 0 5)
0
#+END_SRC
Delighted, Alyssa uses `new-if' to rewrite the square-root program:
#+BEGIN_SRC scheme
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
#+END_SRC
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
#+BEGIN_EXAMPLE
x/y^2 + 2y
----------
3
#+END_EXAMPLE
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.)
-------------------------------------------------------------------