mirror of
https://github.com/correl/sicp.git
synced 2024-11-23 11:09:57 +00:00
1.1 in org format
This commit is contained in:
parent
a95bcc6668
commit
8db66297da
2 changed files with 279 additions and 243 deletions
279
1-1.org
Normal file
279
1-1.org
Normal file
|
@ -0,0 +1,279 @@
|
|||
#+BEGIN_HTML
|
||||
---
|
||||
title: 1.1 - The Elements of Programming
|
||||
layout: page
|
||||
---
|
||||
#+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.)
|
||||
|
||||
-------------------------------------------------------------------
|
243
1-1.scm
243
1-1.scm
|
@ -1,243 +0,0 @@
|
|||
;; ====================================================================
|
||||
;; 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.)
|
||||
;; -------------------------------------------------------------------
|
Loading…
Reference in a new issue