diff --git a/1/1.1.scm b/1/1.1.scm new file mode 100644 index 0000000..e8f690f --- /dev/null +++ b/1/1.1.scm @@ -0,0 +1,57 @@ +; 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. +; +; ============================================================================== +; +; I ran these expressions in the Edwin "interaction window" by typing them out, +; moving my cursor to the end, and typing C-x C-e. + +10 +;Value: 10 + +(+ 5 3 4) +;Value: 12 + +(- 9 1) +;Value: 8 + +(/ 6 2) +;Value: 3 + +(+ (* 2 4) (- 4 6)) +;Value: 6 + +(define a 3) +;Value: a + +(define b (+ a 1)) +;Value: b + +(+ a b (* a b)) +;Value: 19 + +(= a b) +;Value: #f + +(if (and (> b a) (< b (* a b))) + b + a) +;Value: 4 + +(cond ((= a 4) 6) + ((= b 4) (+ 6 7 a)) + (else 25)) +;Value: 16 + +(+ 2 (if (> b a) b a)) +;Value: 6 + +(* (cond ((> a b) a) + ((< a b) b) + (else -1)) + (+ a 1)) +;Value: 16 + diff --git a/1/1.2.scm b/1/1.2.scm new file mode 100644 index 0000000..57fefe1 --- /dev/null +++ b/1/1.2.scm @@ -0,0 +1,13 @@ +; Exercise 1.2 +; +; Translate the following expression into prefix form: +; +; (5 + 4 + (2 - (3 - (6 + 4 / 5)))) / (3 * (6 - 2) * (2 - 7)) +; +; ============================================================================== +; +; It helps to draw out the expression tree on a sheet of paper. + +(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) + (* 3 (- 6 2) (- 2 7))) +;Value: -37/150 \ No newline at end of file diff --git a/1/1.3.scm b/1/1.3.scm new file mode 100644 index 0000000..000fdd9 --- /dev/null +++ b/1/1.3.scm @@ -0,0 +1,20 @@ +; Exercise 1.3 +; +; Define a procedure that takes three numbers as arguments and returns the sum +; of the squares of the two larger numbers. +; +; ============================================================================== +; +; We have to use the `define` syntax for procedures: +; +; (define ( ) ) + +; Defined in section 1.1.4: +(define (square x) (* x x)) +(define (sum-of-squares x y) + (+ (square x) (square y))) + +(define (sum-of-squares-of-two-largest x y z) + (cond ((and (>= y x) (>= z x)) (sum-of-squares y z)) + ((and (>= x y) (>= z y)) (sum-of-squares x z)) + ((and (>= x z) (>= y z)) (sum-of-squares x y)))) \ No newline at end of file diff --git a/1/1.4.scm b/1/1.4.scm new file mode 100644 index 0000000..4227016 --- /dev/null +++ b/1/1.4.scm @@ -0,0 +1,14 @@ +; 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)) +; +; ============================================================================== + +; The body of this procedure is a combination whose operator is itself an if- +; statement. If b > 0, the operator will be "+". Otherwise, it will be "-", in +; this way ensuring that a is summed with the absolute value of b. \ No newline at end of file diff --git a/1/1.5.scm b/1/1.5.scm new file mode 100644 index 0000000..7d57286 --- /dev/null +++ b/1/1.5.scm @@ -0,0 +1,32 @@ +; 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.) +; +; ============================================================================== + +; An interpreter using applicative-order evaluation will hang in an infinite +; loop, since the arguments to `test` will be evaluated first and `p` is +; infinitely recursive. + +; On the other hand, a normal-order evaluation would evaluate to `0`, because +; `p` doesn't get invoked unless the predicate in the `if` statement is false. \ No newline at end of file diff --git a/1/1.6.scm b/1/1.6.scm new file mode 100644 index 0000000..80f5de5 --- /dev/null +++ b/1/1.6.scm @@ -0,0 +1,36 @@ +; 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. +; +; ============================================================================== + +; This new-if procedure is not a special form but rather a procedure call, and +; therefore all of the arguments will be evaluated first before they are passed +; to `cond`. This means that the predicate is ignored and the new `sqrt-iter` +; procedure will call itself recursively forever. \ No newline at end of file diff --git a/1/1.7.scm b/1/1.7.scm new file mode 100644 index 0000000..9e50723 --- /dev/null +++ b/1/1.7.scm @@ -0,0 +1,41 @@ +; 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? +; +; ============================================================================== + +; "Limited precision" in this context means that we are using a finite amount of +; bits to represent a real number with a potentially infinite decimal +; representation. IEEE floating point arithmetic is defined as real-number +; arithmetic truncated to the closest representable float, introducing errors in +; calculations. + +(define (square x) (* x x)) + +(define (average x y) + (/ (+ x y) 2)) + +(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 epsilon 1e-10) +(define (good-enough? guess x) + (< (abs (- guess (improve guess x))) + (* guess epsilon))) + +(define (sqrt x) + (sqrt-iter 1.0 x)) \ No newline at end of file diff --git a/1/1.8.scm b/1/1.8.scm new file mode 100644 index 0000000..2f7c55c --- /dev/null +++ b/1/1.8.scm @@ -0,0 +1,32 @@ +; 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 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.) +; +; ============================================================================== + +(define (square x) (* x x)) + +(define (cube-root x) + (cube-root-iter 1.0 x)) + +(define (cube-root-iter guess x) + (if (good-enough? guess x) + guess + (cube-root-iter (improve guess x) x))) + +; From exercise 1.7 +(define epsilon 1e-20) +(define (good-enough? guess x) + (< (abs (- guess (improve guess x))) + (* guess epsilon))) + +(define (improve guess x) + (/ (+ (/ x (square guess)) (* 2 guess)) 3)) \ No newline at end of file