From: Ramakrishnan Muthukrishnan Date: Thu, 22 Apr 2010 18:53:59 +0000 (+0530) Subject: reorganisation of directories X-Git-Url: https://git.rkrishnan.org/pf/content/en/service/quickstart.html?a=commitdiff_plain;h=751dff6ba0af4cea6b0f172919005ae56f350c39;p=sicp.git reorganisation of directories --- diff --git a/pom.xml b/pom.xml index 62b756b..2f380fb 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ - src/main/clojure + src diff --git a/src/main/clojure/sicp/ch1_1.clj b/src/main/clojure/sicp/ch1_1.clj deleted file mode 100644 index 34856cd..0000000 --- a/src/main/clojure/sicp/ch1_1.clj +++ /dev/null @@ -1,297 +0,0 @@ -(ns sicp.ch1-1) - -(defn square [x] (* x x)) - -(defn sum-of-squares [x y] - (+ (square x) (square y))) - -(defn f [a] - (sum-of-squares (+ a 1) (* a 2))) - -(defn abs - "find absolute value of x" - [x] - (if (< x 0) (- x) x)) - -(defn abs1 [x] - (cond (< x 0) (- x) - :else x)) - -;; exercise 1.1: What is the result printed by the interpreter in response -;; to each expression (in order) ? - -(def a 3) -(def b (+ a 1)) - -(+ a b (* a b)) ; 19 -(= a b) ; false - -(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 given expression into prefix form -(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 1 5))))) - (* 3 (- 6 2) (- 2 7))) ; -71/300 - -;; exercise 1.3: Define a procedure that takes three numbers as -;; arguments and returns the sum of the squares of -;; the two larger numbers. -(defn sort3 [a b c] - (cond (> b a) (sort3 b a c) - (< b c) (sort3 a c b) - :else [a b c])) - -(defn sum-of-sq-of-two-largest [a b c] - (apply sum-of-squares (take 2 (sort3 a b c)))) - -;; well, I cheated above. Let me use only the constructs introduced -;; so far in the book. (follows after the sicp meetup #2 on 28/mar/2010. -(defn sum-of-square-of-two-largest [a b c] - (if (> a b) - (if (> b c) - (sum-of-squares a b) ; a > b > c - (sum-of-squares a c)) - (if (> a c) - (sum-of-squares b a) - (sum-of-squares b c)))) - -;; 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: -;; (defn a-plus-abs-b [a b] -;; ((if (> b 0) + -) a b)) -(comment - If b is positive, we do (+ a b) and if it is negative, we do (- a b). - This makes use of the fact that the first element in a list is an - operand. Here, the operand is chosen based on other operators. - ) - -;; 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: -;; (defn p [] (p)) -;; (defn 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? -(comment - In the case of applicative order evaluation, the test gets into - and infinite loop (eventually using all the stack), as the parameters - are evaluated before they are actualy used in the function. - ) -;; What behavior will he observe with an interpreter that uses -;; normal-order evaluation? Explain your answer. -(comment - It will print 0, as (p) is not evaluated in this case. - ) - -;; 1.1.7 Square root finding using Newton's method -(defn average [x y] - (/ (+ x y) 2)) - -(defn improve [guess x] - (average guess (/ x guess))) - -(defn good-enough? [guess x] - (< (abs (- (square guess) x)) 0.001)) - -(defn sqrt-iter [guess x] - (if (good-enough? guess x) - guess - (sqrt-iter (improve guess x) - x))) - -(defn sqrt [x] - (sqrt-iter 1.0 x)) - -;; 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?'' -(defn new-if [predicate then-clause else-clause] - (cond predicate then-clause - :else else-clause)) - -(new-if (= 3 2) 0 5) ; 5 -(new-if (= 1 1) 0 5) ; 0 - -;; Delighted, Alyssa uses new-if to rewrite the square-root program: - -(defn 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. -(comment - Since `new-if' is a function, when it is called from sqrt-iter, the parameters - are evaluated before it gets called. good-enough? will return a false unless - the guess and x are almost the same. guess evaluated to the initial value of - guess. sqrt-iter gets evaluated, but gets into an infinite loop. The predicate - will have no effect.) - -;; 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. -(comment - user> (sqrt (square 0.001)) - 0.031260655525445276 - user> (sqrt (square 0.2)) - 0.20060990407779591 - user> (sqrt (square 0.01)) - 0.03230844833048122 - user> (sqrt (square 0.02)) - 0.0354008825558513 - user> (sqrt (square 10)) - 10.000000000139897 - user> (sqrt (square 100)) - 100.00000025490743 - user> (sqrt (square 200)) - 200.000000510076 - user> (sqrt (square 2)) - 2.0000000929222947 - user> (sqrt (square 0.1)) - 0.10032578510960607 - user> (sqrt (square 0.01)) - 0.03230844833048122 - user> (sqrt (square 10000)) - 10000.0 - user> (sqrt (square 20000)) - 20000.0 - user> (sqrt (square 200000)) - 200000.0 - user> (sqrt (square 20000000)) - 2.0E7 - user> (sqrt (square 20000000000)) - 2.0E10 - user> (sqrt (square 200000.012)) - 200000.012 - user> (sqrt (square 2000000.123)) - 2000000.123 - user> (sqrt (square 200000000.123)) - 2.00000000123E8 - user> (sqrt (square 2000000000.123)) - 2.000000000123E9 - user> (sqrt (square 20000000000.123)) - 2.0000000000123E10 - user> (sqrt (square 2000000000000.123)) - 2.000000000000123E12 - ) -;; 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. -(defn sqrt-iter [old-guess new-guess x] - (if (good-enough? old-guess new-guess x) - new-guess - (sqrt-iter new-guess (improve new-guess x) - x))) - -(defn improve [guess x] - (average guess (/ x guess))) - -(defn average [x y] - (/ (+ x y) 2)) - -(defn good-enough? [old-guess new-guess x] - (< (/ (abs (- new-guess old-guess)) new-guess) 0.0001)) - -(defn sqrt [x] - (sqrt-iter x 1.0 x)) -(comment -user> (sqrt (square 0.01)) -0.010000000025490743 -user> (sqrt (square 0.001)) -0.0010000000000000117 -user> (sqrt (square 0.0001)) -1.0000000000082464E-4 -user> (sqrt (square 0.02)) -0.020000000050877154 -user> (sqrt (square 0.002)) -0.0020000000000000235 -user> (sqrt (square 4)) -4.000000000000051 -user> (sqrt (square 20)) -20.000000000298428 -user> (sqrt (square 25)) -25.000000063076968 -user> (sqrt 5) -2.236067977499978 -user> (sqrt 25) -5.000000000053722 -user> (sqrt 9) -3.000000001396984 -user> (sqrt 81) -9.000000000007091 -) -;; exercise 1.8: cube root -(defn cube [x] - (* x x x)) - -(defn improve [guess x] - (/ (+ (/ x (square guess)) (* 2 guess)) 3)) - -(defn cubert-iter [old-guess new-guess x] - (if (good-enough? old-guess new-guess x) - new-guess - (cubert-iter new-guess (improve new-guess x) - x))) - -(defn cuberoot [x] - (cubert-iter x 1.0 x)) - -(comment -user> (cuberoot (cube 2)) -2.000000000012062 -user> (cuberoot (cube 10)) -10.000000000000002 -user> (cuberoot (cube 9)) -9.000000000053902 -user> (cuberoot (cube 0.001)) -0.001000000000000962 -user> (cuberoot (cube 0.0001)) -1.000000000000001E-4 -user> -) -;; section 1.1.8 -;; hiding the non-public procedure definitions -(defn- sqrt-iter [guess x] - (if (good-enough? guess x) - guess - (sqrt-iter (improve guess x) - x))) - -(defn- improve [guess x] - (average guess (/ x guess))) - -(defn- average [x y] - (/ (+ x y) 2)) - -(defn- good-enough? [guess x] - (< (abs (- (square guess) x)) 0.001)) - -(defn sqrt [x] - (sqrt-iter 1.0 x)) diff --git a/src/main/clojure/sicp/ch1_2.clj b/src/main/clojure/sicp/ch1_2.clj deleted file mode 100644 index 18c14bd..0000000 --- a/src/main/clojure/sicp/ch1_2.clj +++ /dev/null @@ -1,559 +0,0 @@ -(ns sicp.ch1-2 - (:use (clojure.contrib trace math))) - - -(defn factorial [n] - (if (= n 1) - 1 - (* n (factorial (- n 1))))) - -;; stack friendly version -(defn factorial2 [n] - (loop [x n acc 1] - (if (= x 1) - acc - (recur (- x 1) (* acc x))))) - -;; even better -(defn factorial3 [n] - (reduce * (range 1 (inc n)))) - -;; (comment -;; user> (dotrace [factorial] (factorial 3)) -;; TRACE t2701: (factorial 3) -;; TRACE t2702: | (factorial 2) -;; TRACE t2703: | | (factorial 1) -;; TRACE t2703: | | => 1 -;; TRACE t2702: | => 2 -;; TRACE t2701: => 6 -;; 6 -;; ) - -;; (comment -;; sicp.chapter1.ch1_2> (dotrace [factorial] (factorial 6)) -;; TRACE t2778: (factorial 6) -;; TRACE t2779: | (factorial 5) -;; TRACE t2780: | | (factorial 4) -;; TRACE t2781: | | | (factorial 3) -;; TRACE t2782: | | | | (factorial 2) -;; TRACE t2783: | | | | | (factorial 1) -;; TRACE t2783: | | | | | => 1 -;; TRACE t2782: | | | | => 2 -;; TRACE t2781: | | | => 6 -;; TRACE t2780: | | => 24 -;; TRACE t2779: | => 120 -;; TRACE t2778: => 720 -;; 720 -;; ) - -;; (comment -;; sicp.chapter1.ch1_2> (dotrace [factorial2] (factorial2 6)) -;; TRACE t2806: (factorial2 6) -;; TRACE t2806: => 720 -;; 720 -;; ) - -(defn fact-iter [product counter max-count] - (if (> counter max-count) - product - (fact-iter (* product counter) - (inc counter) - max-count))) - -(defn factorial [n] - (fact-iter 1 1 n)) - -;; (comment -;; user> (dotrace [factorial fact-iter] (factorial 6)) -;; TRACE t2378: (factorial 6) -;; TRACE t2379: | (fact-iter 1 1 6) -;; TRACE t2380: | | (fact-iter 1 2 6) -;; TRACE t2381: | | | (fact-iter 2 3 6) -;; TRACE t2382: | | | | (fact-iter 6 4 6) -;; TRACE t2383: | | | | | (fact-iter 24 5 6) -;; TRACE t2384: | | | | | | (fact-iter 120 6 6) -;; TRACE t2385: | | | | | | | (fact-iter 720 7 6) -;; TRACE t2385: | | | | | | | => 720 -;; TRACE t2384: | | | | | | => 720 -;; TRACE t2383: | | | | | => 720 -;; TRACE t2382: | | | | => 720 -;; TRACE t2381: | | | => 720 -;; TRACE t2380: | | => 720 -;; TRACE t2379: | => 720 -;; TRACE t2378: => 720 -;; 720 -;; ) - -;; observation: clojure loop-recur construct is essentially the same as -;; the iterative version. - -;; exercise 1.9 -(defn ++ [a b] - (if (= a 0) - b - (inc (++ (dec a) b)))) - -;; (comment -;; This version is a recursive process, where the previous call increments -;; the sum by 1 and each call decrement the first operand by 1. - -;; user> (dotrace [++] (++ 4 5)) -;; TRACE t3745: (++ 4 5) -;; TRACE t3746: | (++ 3 5) -;; TRACE t3747: | | (++ 2 5) -;; TRACE t3748: | | | (++ 1 5) -;; TRACE t3749: | | | | (++ 0 5) -;; TRACE t3749: | | | | => 5 -;; TRACE t3748: | | | => 6 -;; TRACE t3747: | | => 7 -;; TRACE t3746: | => 8 -;; TRACE t3745: => 9 -;; 9 -;; ) - -(defn ++ [a b] - (if (= a 0) - b - (++ (dec a) (inc b)))) - -;; (comment - -;; user> (dotrace [++] (++ 4 5)) -;; TRACE t3766: (++ 4 5) -;; TRACE t3767: | (++ 3 6) -;; TRACE t3768: | | (++ 2 7) -;; TRACE t3769: | | | (++ 1 8) -;; TRACE t3770: | | | | (++ 0 9) -;; TRACE t3770: | | | | => 9 -;; TRACE t3769: | | | => 9 -;; TRACE t3768: | | => 9 -;; TRACE t3767: | => 9 -;; TRACE t3766: => 9 -;; 9 -;; ) - -;; exercise 1.10 -;; ackerman functions -(defn A [x y] - (cond (= y 0) 0 - (= x 0) (* 2 y) - (= y 1) 2 - :else (A (- x 1) - (A x (- y 1))))) - -(comment -user> (A 1 10) -1024 -user> (A 2 4) -65536 -user> (A 3 3) -65536 -) - -(defn f [n] (A 0 n)) ; f(n) = 2n -(defn g [n] (A 1 n)) ; g(n) = 2^n -;; (comment -;; g (n) = A (1,n) -;; = A (0, A (1, n-1)) = f (A(1,n-1)) -;; = f (f (1,n-2)) -;; ..... -;; = f (f (f ... f (1,(n- (n-1))))) -;; = f (f (f ... 2)) -;; = 2 * (2^(n-1)) -;; = 2^n -;; ) - -(defn h [n] (A 2 n)) ; h(n) = 2^(n^2) - -;; section 1.2.2: Tree Recursion -(defn fib [n] - (cond (= n 0) 0 - (= n 1) 1 - :else (+ (fib (- n 1)) - (fib (- n 2))))) - -;; iterative version -(defn fib-iter [a b count] - (if (= count 0) - b - (fib-iter (+ a b) a (dec count)))) - -(defn fib [n] - (fib-iter 1 0 n)) - -;; example: counting changes -(defn first-denomination [kinds-of-coins] - (cond (= kinds-of-coins 1) 1 - (= kinds-of-coins 2) 5 - (= kinds-of-coins 3) 10 - (= kinds-of-coins 4) 25 - (= kinds-of-coins 5) 50)) - - -(defn first-denomination [kinds-of-coins] - ({1 1 2 5 3 10 4 25 5 50} kinds-of-coins)) - -(defn cc [amount kinds-of-coins] - (cond (= amount 0) 1 - (or (< amount 0) (= kinds-of-coins 0)) 0 - :else (+ (cc amount (- kinds-of-coins 1)) - (cc (- amount - (first-denomination kinds-of-coins)) - kinds-of-coins)))) - -(defn count-change [amount] - (cc amount 5)) - -;; exercise 1.11: A function f is defined by the rule that f(n) = n if n < 3 -;; and f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3) if n> 3. -;; Write a procedure that computes f by means of a recursive -;; process. Write a procedure that computes f by means of an -;; iterative process. -(defn f [n] - (if (< n 3) - n - (+ (f (- n 1)) - (* 2 (f (- n 2))) - (* 3 (f (- n 3)))))) - -(comment -user> (map f (range 10)) -(0 1 2 4 11 25 59 142 335 796) -) - -;; ex 1.11: iterative version -(defn f-iter [count prev0 prev1 prev2] - (if (= count 3) - (+ prev0 - (* 2 prev1) - (* 3 prev2)) - (f-iter (dec count) - (+ prev0 - (* 2 prev1) - (* 3 prev2)) - prev0 - prev1))) - -(defn f [n] - (if (< n 3) - n - (f-iter n 2 1 0))) - -;; ex 1.11: iterative version with let -(defn f-iter [count prev0 prev1 prev2] - (let [res (+ prev0 (* 2 prev1) (* 3 prev2))] - (if (= count 3) - res - (f-iter (dec count) - res - prev0 - prev1)))) - -;; exercise 1.12. 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. -(defn pascal [row col] - (when (<= col row) - (if (or (= col 0) (= row col)) - 1 - (+ (pascal (dec row) col) - (pascal (dec row) (dec col)))))) - -;; exercise 1.13: -(comment -See the pdfs in the directory for the answers. -) - -;; ex 1.13 (contd) -(defn fib-approx [n] - (let [phi (/ (+ 1 (sqrt 5)) 2)] - (/ (expt phi n) (sqrt 5)))) - -;; (comment -;; user> (map fib-approx (range 10)) -;; (0.4472135954999579 0.7236067977499789 1.1708203932499368 1.8944271909999157 3.065247584249853 4.959674775249769 8.024922359499623 12.984597134749393 21.009519494249016 33.99411662899841) -;; ) - -;; exercise 1.14: tree of (count-changes 11) -(comment - See the pdf for the tree representation. -) - - -;; order of size and computation -;; see PDF, but below is the trace tree. -;; (comment -;; user> (use 'clojure.contrib.trace) -;; nil -;; user> (dotrace [count-change cc] (count-change 11)) -;; TRACE t2609: (count-change 11) -;; TRACE t2610: | (cc 11 5) -;; TRACE t2611: | | (cc 11 4) -;; TRACE t2612: | | | (cc 11 3) -;; TRACE t2613: | | | | (cc 11 2) -;; TRACE t2614: | | | | | (cc 11 1) -;; TRACE t2615: | | | | | | (cc 11 0) -;; TRACE t2615: | | | | | | => 0 -;; TRACE t2616: | | | | | | (cc 10 1) -;; TRACE t2617: | | | | | | | (cc 10 0) -;; TRACE t2617: | | | | | | | => 0 -;; TRACE t2618: | | | | | | | (cc 9 1) -;; TRACE t2619: | | | | | | | | (cc 9 0) -;; TRACE t2619: | | | | | | | | => 0 -;; TRACE t2620: | | | | | | | | (cc 8 1) -;; TRACE t2621: | | | | | | | | | (cc 8 0) -;; TRACE t2621: | | | | | | | | | => 0 -;; TRACE t2622: | | | | | | | | | (cc 7 1) -;; TRACE t2623: | | | | | | | | | | (cc 7 0) -;; TRACE t2623: | | | | | | | | | | => 0 -;; TRACE t2624: | | | | | | | | | | (cc 6 1) -;; TRACE t2625: | | | | | | | | | | | (cc 6 0) -;; TRACE t2625: | | | | | | | | | | | => 0 -;; TRACE t2626: | | | | | | | | | | | (cc 5 1) -;; TRACE t2627: | | | | | | | | | | | | (cc 5 0) -;; TRACE t2627: | | | | | | | | | | | | => 0 -;; TRACE t2628: | | | | | | | | | | | | (cc 4 1) -;; TRACE t2629: | | | | | | | | | | | | | (cc 4 0) -;; TRACE t2629: | | | | | | | | | | | | | => 0 -;; TRACE t2630: | | | | | | | | | | | | | (cc 3 1) -;; TRACE t2631: | | | | | | | | | | | | | | (cc 3 0) -;; TRACE t2631: | | | | | | | | | | | | | | => 0 -;; TRACE t2632: | | | | | | | | | | | | | | (cc 2 1) -;; TRACE t2633: | | | | | | | | | | | | | | | (cc 2 0) -;; TRACE t2633: | | | | | | | | | | | | | | | => 0 -;; TRACE t2634: | | | | | | | | | | | | | | | (cc 1 1) -;; TRACE t2635: | | | | | | | | | | | | | | | | (cc 1 0) -;; TRACE t2635: | | | | | | | | | | | | | | | | => 0 -;; TRACE t2636: | | | | | | | | | | | | | | | | (cc 0 1) -;; TRACE t2636: | | | | | | | | | | | | | | | | => 1 -;; TRACE t2634: | | | | | | | | | | | | | | | => 1 -;; TRACE t2632: | | | | | | | | | | | | | | => 1 -;; TRACE t2630: | | | | | | | | | | | | | => 1 -;; TRACE t2628: | | | | | | | | | | | | => 1 -;; TRACE t2626: | | | | | | | | | | | => 1 -;; TRACE t2624: | | | | | | | | | | => 1 -;; TRACE t2622: | | | | | | | | | => 1 -;; TRACE t2620: | | | | | | | | => 1 -;; TRACE t2618: | | | | | | | => 1 -;; TRACE t2616: | | | | | | => 1 -;; TRACE t2614: | | | | | => 1 -;; TRACE t2637: | | | | | (cc 6 2) -;; TRACE t2638: | | | | | | (cc 6 1) -;; TRACE t2639: | | | | | | | (cc 6 0) -;; TRACE t2639: | | | | | | | => 0 -;; TRACE t2640: | | | | | | | (cc 5 1) -;; TRACE t2641: | | | | | | | | (cc 5 0) -;; TRACE t2641: | | | | | | | | => 0 -;; TRACE t2642: | | | | | | | | (cc 4 1) -;; TRACE t2643: | | | | | | | | | (cc 4 0) -;; TRACE t2643: | | | | | | | | | => 0 -;; TRACE t2644: | | | | | | | | | (cc 3 1) -;; TRACE t2645: | | | | | | | | | | (cc 3 0) -;; TRACE t2645: | | | | | | | | | | => 0 -;; TRACE t2646: | | | | | | | | | | (cc 2 1) -;; TRACE t2647: | | | | | | | | | | | (cc 2 0) -;; TRACE t2647: | | | | | | | | | | | => 0 -;; TRACE t2648: | | | | | | | | | | | (cc 1 1) -;; TRACE t2649: | | | | | | | | | | | | (cc 1 0) -;; TRACE t2649: | | | | | | | | | | | | => 0 -;; TRACE t2650: | | | | | | | | | | | | (cc 0 1) -;; TRACE t2650: | | | | | | | | | | | | => 1 -;; TRACE t2648: | | | | | | | | | | | => 1 -;; TRACE t2646: | | | | | | | | | | => 1 -;; TRACE t2644: | | | | | | | | | => 1 -;; TRACE t2642: | | | | | | | | => 1 -;; TRACE t2640: | | | | | | | => 1 -;; TRACE t2638: | | | | | | => 1 -;; TRACE t2651: | | | | | | (cc 1 2) -;; TRACE t2652: | | | | | | | (cc 1 1) -;; TRACE t2653: | | | | | | | | (cc 1 0) -;; TRACE t2653: | | | | | | | | => 0 -;; TRACE t2654: | | | | | | | | (cc 0 1) -;; TRACE t2654: | | | | | | | | => 1 -;; TRACE t2652: | | | | | | | => 1 -;; TRACE t2655: | | | | | | | (cc -4 2) -;; TRACE t2655: | | | | | | | => 0 -;; TRACE t2651: | | | | | | => 1 -;; TRACE t2637: | | | | | => 2 -;; TRACE t2613: | | | | => 3 -;; TRACE t2656: | | | | (cc 1 3) -;; TRACE t2657: | | | | | (cc 1 2) -;; TRACE t2658: | | | | | | (cc 1 1) -;; TRACE t2659: | | | | | | | (cc 1 0) -;; TRACE t2659: | | | | | | | => 0 -;; TRACE t2660: | | | | | | | (cc 0 1) -;; TRACE t2660: | | | | | | | => 1 -;; TRACE t2658: | | | | | | => 1 -;; TRACE t2661: | | | | | | (cc -4 2) -;; TRACE t2661: | | | | | | => 0 -;; TRACE t2657: | | | | | => 1 -;; TRACE t2662: | | | | | (cc -9 3) -;; TRACE t2662: | | | | | => 0 -;; TRACE t2656: | | | | => 1 -;; TRACE t2612: | | | => 4 -;; TRACE t2663: | | | (cc -14 4) -;; TRACE t2663: | | | => 0 -;; TRACE t2611: | | => 4 -;; TRACE t2664: | | (cc -39 5) -;; TRACE t2664: | | => 0 -;; TRACE t2610: | => 4 -;; TRACE t2609: => 4 -;; 4 -;; ) - - -;; TODO: orders of growth in space and number of steps. - -;; exercise 1.15: sin (x) calculation -;; a. How many times is the procedure p applied when (sine 12.15) -;; is evaluated? -;; b. What is the order of growth in space and number of steps (as -;; a function of a) used by the process generated by the sine -;; procedure when (sine a) is evaluated? -(defn cube [x] (* x x x)) - -(defn p [x] (- (* 3 x) (* 4 (cube x)))) - -(defn sine [angle] - (if (not (> (abs angle) 0.1)) - angle - (p (sine (/ angle 3.0))))) - -;; solution to (a) => 5 -;; (comment -;; user> (dotrace [p] (sine 12.15)) -;; TRACE t2490: (p 0.049999999999999996) -;; TRACE t2490: => 0.1495 -;; TRACE t2491: (p 0.1495) -;; TRACE t2491: => 0.4351345505 -;; TRACE t2492: (p 0.4351345505) -;; TRACE t2492: => 0.9758465331678772 -;; TRACE t2493: (p 0.9758465331678772) -;; TRACE t2493: => -0.7895631144708228 -;; TRACE t2494: (p -0.7895631144708228) -;; TRACE t2494: => -0.39980345741334 -;; -0.39980345741334 -;; ) - -;; solution to b -;; both space and number of steps grows as log3(a) -> log a to the base 3. -;; -;; proof: -;; a * (1/3)^n <= 0.1 -;; => take log to the base 3 on both the sides. - -;; Note: Finding the order of space in a recursive process is sort of, equiv -;; to finding the number of deferred operations. Which is in-turn the -;; same as the depth of the evaluation tree. - -;; 1.2.4: exponentiation -;; computing b^n - -;; iterative -(defn expt-iter [base counter product] - (if (= counter 0) - product - (expt-iter base - (dec counter) - (* product base)))) - -(defn myexpt [b n] - (expt-iter b n 1)) - -(defn myexpt [b n] - (if (= n 0) - 1 - (* b (myexpt b (dec n))))) - -;; fast version -(defn square [x] - (* x x)) - -(defn fast-expt [b n] - (cond (= n 0) 1 - (even? n) (square (fast-expt b (/ n 2))) - :else (* b (fast-expt b (dec n))))) - -;; exercise 1.16: -(defn myexpt [b n] - (expt-iter b n 1)) - -(defn expt-iter [b n a] - (cond (= n 0) a - (even? n) (expt-iter (square b) (/ n 2) a) - :else (expt-iter b (- n 1) (* a b)))) - -;; exercise 1.17: -(defn mult [a b] - (if (= b 0) - 0 - (+ a (mult a (- b 1))))) - -;; double -(defn twice [x] - (* 2 x)) - -(defn half [x] - (/ x 2)) - -;; product = 2 * (a * (b/2)) for even b -;; = a + (a * (b - 1)) for odd b -(defn fast-mult [a b] - (cond (= b 0) 0 - (= b 1) a - (even? b) (twice (fast-mult a (half b))) - :else (+ a (fast-mult a (- b 1))))) - -;; exercise 1.18: iterative multiply thru addition -;; the idea is to keep a state variable. -(defn fast-mult-iter [a b k] - (cond (= b 0) k - (even? b) (fast-mult-iter (twice a) (half b) k) - :else (fast-mult-iter a (- b 1) (+ k a)))) - -(defn fast-mult-new [a b] - (fast-mult-iter a b 0)) - -;; (comment -;; user> (dotrace [fast-mult-new fast-mult-iter] (fast-mult-new 2 3)) -;; TRACE t2915: (fast-mult-new 2 3) -;; TRACE t2916: | (fast-mult-iter 2 3 0) -;; TRACE t2917: | | (fast-mult-iter 2 2 2) -;; TRACE t2918: | | | (fast-mult-iter 4 1 2) -;; TRACE t2919: | | | | (fast-mult-iter 4 0 6) -;; TRACE t2919: | | | | => 6 -;; TRACE t2918: | | | => 6 -;; TRACE t2917: | | => 6 -;; TRACE t2916: | => 6 -;; TRACE t2915: => 6 -;; 6 -;; ) - -;; exercise 1.19: fast fibonacci -;; see the pdf of the notebook scan for the derivation of p' and q' -(defn ffib-iter [a b p q count] - (cond (= count 0) b - (even? count) - (ffib-iter a - b - (+ (* p p) (* q q)) - (+ (* 2 p q) (* q q)) - (/ count 2)) - :else (ffib-iter (+ (* b q) (* a q) (* a p)) - (+ (* b p) (* a q)) - p - q - (- count 1)))) - -(defn ffib [n] - (ffib-iter 1 0 0 1 n)) - diff --git a/src/sicp/ch1_1.clj b/src/sicp/ch1_1.clj new file mode 100644 index 0000000..34856cd --- /dev/null +++ b/src/sicp/ch1_1.clj @@ -0,0 +1,297 @@ +(ns sicp.ch1-1) + +(defn square [x] (* x x)) + +(defn sum-of-squares [x y] + (+ (square x) (square y))) + +(defn f [a] + (sum-of-squares (+ a 1) (* a 2))) + +(defn abs + "find absolute value of x" + [x] + (if (< x 0) (- x) x)) + +(defn abs1 [x] + (cond (< x 0) (- x) + :else x)) + +;; exercise 1.1: What is the result printed by the interpreter in response +;; to each expression (in order) ? + +(def a 3) +(def b (+ a 1)) + +(+ a b (* a b)) ; 19 +(= a b) ; false + +(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 given expression into prefix form +(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 1 5))))) + (* 3 (- 6 2) (- 2 7))) ; -71/300 + +;; exercise 1.3: Define a procedure that takes three numbers as +;; arguments and returns the sum of the squares of +;; the two larger numbers. +(defn sort3 [a b c] + (cond (> b a) (sort3 b a c) + (< b c) (sort3 a c b) + :else [a b c])) + +(defn sum-of-sq-of-two-largest [a b c] + (apply sum-of-squares (take 2 (sort3 a b c)))) + +;; well, I cheated above. Let me use only the constructs introduced +;; so far in the book. (follows after the sicp meetup #2 on 28/mar/2010. +(defn sum-of-square-of-two-largest [a b c] + (if (> a b) + (if (> b c) + (sum-of-squares a b) ; a > b > c + (sum-of-squares a c)) + (if (> a c) + (sum-of-squares b a) + (sum-of-squares b c)))) + +;; 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: +;; (defn a-plus-abs-b [a b] +;; ((if (> b 0) + -) a b)) +(comment + If b is positive, we do (+ a b) and if it is negative, we do (- a b). + This makes use of the fact that the first element in a list is an + operand. Here, the operand is chosen based on other operators. + ) + +;; 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: +;; (defn p [] (p)) +;; (defn 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? +(comment + In the case of applicative order evaluation, the test gets into + and infinite loop (eventually using all the stack), as the parameters + are evaluated before they are actualy used in the function. + ) +;; What behavior will he observe with an interpreter that uses +;; normal-order evaluation? Explain your answer. +(comment + It will print 0, as (p) is not evaluated in this case. + ) + +;; 1.1.7 Square root finding using Newton's method +(defn average [x y] + (/ (+ x y) 2)) + +(defn improve [guess x] + (average guess (/ x guess))) + +(defn good-enough? [guess x] + (< (abs (- (square guess) x)) 0.001)) + +(defn sqrt-iter [guess x] + (if (good-enough? guess x) + guess + (sqrt-iter (improve guess x) + x))) + +(defn sqrt [x] + (sqrt-iter 1.0 x)) + +;; 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?'' +(defn new-if [predicate then-clause else-clause] + (cond predicate then-clause + :else else-clause)) + +(new-if (= 3 2) 0 5) ; 5 +(new-if (= 1 1) 0 5) ; 0 + +;; Delighted, Alyssa uses new-if to rewrite the square-root program: + +(defn 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. +(comment + Since `new-if' is a function, when it is called from sqrt-iter, the parameters + are evaluated before it gets called. good-enough? will return a false unless + the guess and x are almost the same. guess evaluated to the initial value of + guess. sqrt-iter gets evaluated, but gets into an infinite loop. The predicate + will have no effect.) + +;; 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. +(comment + user> (sqrt (square 0.001)) + 0.031260655525445276 + user> (sqrt (square 0.2)) + 0.20060990407779591 + user> (sqrt (square 0.01)) + 0.03230844833048122 + user> (sqrt (square 0.02)) + 0.0354008825558513 + user> (sqrt (square 10)) + 10.000000000139897 + user> (sqrt (square 100)) + 100.00000025490743 + user> (sqrt (square 200)) + 200.000000510076 + user> (sqrt (square 2)) + 2.0000000929222947 + user> (sqrt (square 0.1)) + 0.10032578510960607 + user> (sqrt (square 0.01)) + 0.03230844833048122 + user> (sqrt (square 10000)) + 10000.0 + user> (sqrt (square 20000)) + 20000.0 + user> (sqrt (square 200000)) + 200000.0 + user> (sqrt (square 20000000)) + 2.0E7 + user> (sqrt (square 20000000000)) + 2.0E10 + user> (sqrt (square 200000.012)) + 200000.012 + user> (sqrt (square 2000000.123)) + 2000000.123 + user> (sqrt (square 200000000.123)) + 2.00000000123E8 + user> (sqrt (square 2000000000.123)) + 2.000000000123E9 + user> (sqrt (square 20000000000.123)) + 2.0000000000123E10 + user> (sqrt (square 2000000000000.123)) + 2.000000000000123E12 + ) +;; 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. +(defn sqrt-iter [old-guess new-guess x] + (if (good-enough? old-guess new-guess x) + new-guess + (sqrt-iter new-guess (improve new-guess x) + x))) + +(defn improve [guess x] + (average guess (/ x guess))) + +(defn average [x y] + (/ (+ x y) 2)) + +(defn good-enough? [old-guess new-guess x] + (< (/ (abs (- new-guess old-guess)) new-guess) 0.0001)) + +(defn sqrt [x] + (sqrt-iter x 1.0 x)) +(comment +user> (sqrt (square 0.01)) +0.010000000025490743 +user> (sqrt (square 0.001)) +0.0010000000000000117 +user> (sqrt (square 0.0001)) +1.0000000000082464E-4 +user> (sqrt (square 0.02)) +0.020000000050877154 +user> (sqrt (square 0.002)) +0.0020000000000000235 +user> (sqrt (square 4)) +4.000000000000051 +user> (sqrt (square 20)) +20.000000000298428 +user> (sqrt (square 25)) +25.000000063076968 +user> (sqrt 5) +2.236067977499978 +user> (sqrt 25) +5.000000000053722 +user> (sqrt 9) +3.000000001396984 +user> (sqrt 81) +9.000000000007091 +) +;; exercise 1.8: cube root +(defn cube [x] + (* x x x)) + +(defn improve [guess x] + (/ (+ (/ x (square guess)) (* 2 guess)) 3)) + +(defn cubert-iter [old-guess new-guess x] + (if (good-enough? old-guess new-guess x) + new-guess + (cubert-iter new-guess (improve new-guess x) + x))) + +(defn cuberoot [x] + (cubert-iter x 1.0 x)) + +(comment +user> (cuberoot (cube 2)) +2.000000000012062 +user> (cuberoot (cube 10)) +10.000000000000002 +user> (cuberoot (cube 9)) +9.000000000053902 +user> (cuberoot (cube 0.001)) +0.001000000000000962 +user> (cuberoot (cube 0.0001)) +1.000000000000001E-4 +user> +) +;; section 1.1.8 +;; hiding the non-public procedure definitions +(defn- sqrt-iter [guess x] + (if (good-enough? guess x) + guess + (sqrt-iter (improve guess x) + x))) + +(defn- improve [guess x] + (average guess (/ x guess))) + +(defn- average [x y] + (/ (+ x y) 2)) + +(defn- good-enough? [guess x] + (< (abs (- (square guess) x)) 0.001)) + +(defn sqrt [x] + (sqrt-iter 1.0 x)) diff --git a/src/sicp/ch1_2.clj b/src/sicp/ch1_2.clj new file mode 100644 index 0000000..cd210be --- /dev/null +++ b/src/sicp/ch1_2.clj @@ -0,0 +1,564 @@ +(ns sicp.ch1-2 + (:use (clojure.contrib trace math))) + + +(defn factorial [n] + (if (= n 1) + 1 + (* n (factorial (- n 1))))) + +;; stack friendly version +(defn factorial2 [n] + (loop [x n acc 1] + (if (= x 1) + acc + (recur (- x 1) (* acc x))))) + +;; even better +(defn factorial3 [n] + (reduce * (range 1 (inc n)))) + +;; (comment +;; user> (dotrace [factorial] (factorial 3)) +;; TRACE t2701: (factorial 3) +;; TRACE t2702: | (factorial 2) +;; TRACE t2703: | | (factorial 1) +;; TRACE t2703: | | => 1 +;; TRACE t2702: | => 2 +;; TRACE t2701: => 6 +;; 6 +;; ) + +;; (comment +;; sicp.chapter1.ch1_2> (dotrace [factorial] (factorial 6)) +;; TRACE t2778: (factorial 6) +;; TRACE t2779: | (factorial 5) +;; TRACE t2780: | | (factorial 4) +;; TRACE t2781: | | | (factorial 3) +;; TRACE t2782: | | | | (factorial 2) +;; TRACE t2783: | | | | | (factorial 1) +;; TRACE t2783: | | | | | => 1 +;; TRACE t2782: | | | | => 2 +;; TRACE t2781: | | | => 6 +;; TRACE t2780: | | => 24 +;; TRACE t2779: | => 120 +;; TRACE t2778: => 720 +;; 720 +;; ) + +;; (comment +;; sicp.chapter1.ch1_2> (dotrace [factorial2] (factorial2 6)) +;; TRACE t2806: (factorial2 6) +;; TRACE t2806: => 720 +;; 720 +;; ) + +(defn fact-iter [product counter max-count] + (if (> counter max-count) + product + (fact-iter (* product counter) + (inc counter) + max-count))) + +(defn factorial [n] + (fact-iter 1 1 n)) + +;; (comment +;; user> (dotrace [factorial fact-iter] (factorial 6)) +;; TRACE t2378: (factorial 6) +;; TRACE t2379: | (fact-iter 1 1 6) +;; TRACE t2380: | | (fact-iter 1 2 6) +;; TRACE t2381: | | | (fact-iter 2 3 6) +;; TRACE t2382: | | | | (fact-iter 6 4 6) +;; TRACE t2383: | | | | | (fact-iter 24 5 6) +;; TRACE t2384: | | | | | | (fact-iter 120 6 6) +;; TRACE t2385: | | | | | | | (fact-iter 720 7 6) +;; TRACE t2385: | | | | | | | => 720 +;; TRACE t2384: | | | | | | => 720 +;; TRACE t2383: | | | | | => 720 +;; TRACE t2382: | | | | => 720 +;; TRACE t2381: | | | => 720 +;; TRACE t2380: | | => 720 +;; TRACE t2379: | => 720 +;; TRACE t2378: => 720 +;; 720 +;; ) + +;; observation: clojure loop-recur construct is essentially the same as +;; the iterative version. + +;; exercise 1.9 +(defn ++ [a b] + (if (= a 0) + b + (inc (++ (dec a) b)))) + +;; (comment +;; This version is a recursive process, where the previous call increments +;; the sum by 1 and each call decrement the first operand by 1. + +;; user> (dotrace [++] (++ 4 5)) +;; TRACE t3745: (++ 4 5) +;; TRACE t3746: | (++ 3 5) +;; TRACE t3747: | | (++ 2 5) +;; TRACE t3748: | | | (++ 1 5) +;; TRACE t3749: | | | | (++ 0 5) +;; TRACE t3749: | | | | => 5 +;; TRACE t3748: | | | => 6 +;; TRACE t3747: | | => 7 +;; TRACE t3746: | => 8 +;; TRACE t3745: => 9 +;; 9 +;; ) + +(defn ++ [a b] + (if (= a 0) + b + (++ (dec a) (inc b)))) + +;; (comment + +;; user> (dotrace [++] (++ 4 5)) +;; TRACE t3766: (++ 4 5) +;; TRACE t3767: | (++ 3 6) +;; TRACE t3768: | | (++ 2 7) +;; TRACE t3769: | | | (++ 1 8) +;; TRACE t3770: | | | | (++ 0 9) +;; TRACE t3770: | | | | => 9 +;; TRACE t3769: | | | => 9 +;; TRACE t3768: | | => 9 +;; TRACE t3767: | => 9 +;; TRACE t3766: => 9 +;; 9 +;; ) + +;; exercise 1.10 +;; ackerman functions +(defn A [x y] + (cond (= y 0) 0 + (= x 0) (* 2 y) + (= y 1) 2 + :else (A (- x 1) + (A x (- y 1))))) + +(comment +user> (A 1 10) +1024 +user> (A 2 4) +65536 +user> (A 3 3) +65536 +) + +(defn f [n] (A 0 n)) ; f(n) = 2n +(defn g [n] (A 1 n)) ; g(n) = 2^n +;; (comment +;; g (n) = A (1,n) +;; = A (0, A (1, n-1)) = f (A(1,n-1)) +;; = f (f (1,n-2)) +;; ..... +;; = f (f (f ... f (1,(n- (n-1))))) +;; = f (f (f ... 2)) +;; = 2 * (2^(n-1)) +;; = 2^n +;; ) + +(defn h [n] (A 2 n)) ; h(n) = 2^(n^2) + +;; section 1.2.2: Tree Recursion +(defn fib [n] + (cond (= n 0) 0 + (= n 1) 1 + :else (+ (fib (- n 1)) + (fib (- n 2))))) + +;; iterative version +(defn fib-iter [a b count] + (if (= count 0) + b + (fib-iter (+ a b) a (dec count)))) + +(defn fib [n] + (fib-iter 1 0 n)) + +;; example: counting changes +(defn first-denomination [kinds-of-coins] + (cond (= kinds-of-coins 1) 1 + (= kinds-of-coins 2) 5 + (= kinds-of-coins 3) 10 + (= kinds-of-coins 4) 25 + (= kinds-of-coins 5) 50)) + + +(defn first-denomination [kinds-of-coins] + ({1 1 2 5 3 10 4 25 5 50} kinds-of-coins)) + +(defn cc [amount kinds-of-coins] + (cond (= amount 0) 1 + (or (< amount 0) (= kinds-of-coins 0)) 0 + :else (+ (cc amount (- kinds-of-coins 1)) + (cc (- amount + (first-denomination kinds-of-coins)) + kinds-of-coins)))) + +(defn count-change [amount] + (cc amount 5)) + +;; exercise 1.11: A function f is defined by the rule that f(n) = n if n < 3 +;; and f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3) if n> 3. +;; Write a procedure that computes f by means of a recursive +;; process. Write a procedure that computes f by means of an +;; iterative process. +(defn f [n] + (if (< n 3) + n + (+ (f (- n 1)) + (* 2 (f (- n 2))) + (* 3 (f (- n 3)))))) + +(comment +user> (map f (range 10)) +(0 1 2 4 11 25 59 142 335 796) +) + +;; ex 1.11: iterative version +(defn f-iter [count prev0 prev1 prev2] + (if (= count 3) + (+ prev0 + (* 2 prev1) + (* 3 prev2)) + (f-iter (dec count) + (+ prev0 + (* 2 prev1) + (* 3 prev2)) + prev0 + prev1))) + +(defn f [n] + (if (< n 3) + n + (f-iter n 2 1 0))) + +;; ex 1.11: iterative version with let +(defn f-iter [count prev0 prev1 prev2] + (let [res (+ prev0 (* 2 prev1) (* 3 prev2))] + (if (= count 3) + res + (f-iter (dec count) + res + prev0 + prev1)))) + +;; exercise 1.12. 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. +(defn pascal [row col] + (when (<= col row) + (if (or (= col 0) (= row col)) + 1 + (+ (pascal (dec row) col) + (pascal (dec row) (dec col)))))) + +;; exercise 1.13: +(comment +See the pdfs in the directory for the answers. +) + +;; ex 1.13 (contd) +(defn fib-approx [n] + (let [phi (/ (+ 1 (sqrt 5)) 2)] + (/ (expt phi n) (sqrt 5)))) + +;; (comment +;; user> (map fib-approx (range 10)) +;; (0.4472135954999579 0.7236067977499789 1.1708203932499368 1.8944271909999157 3.065247584249853 4.959674775249769 8.024922359499623 12.984597134749393 21.009519494249016 33.99411662899841) +;; ) + +;; exercise 1.14: tree of (count-changes 11) +(comment + See the pdf for the tree representation. +) + + +;; order of size and computation +;; see PDF, but below is the trace tree. +;; (comment +;; user> (use 'clojure.contrib.trace) +;; nil +;; user> (dotrace [count-change cc] (count-change 11)) +;; TRACE t2609: (count-change 11) +;; TRACE t2610: | (cc 11 5) +;; TRACE t2611: | | (cc 11 4) +;; TRACE t2612: | | | (cc 11 3) +;; TRACE t2613: | | | | (cc 11 2) +;; TRACE t2614: | | | | | (cc 11 1) +;; TRACE t2615: | | | | | | (cc 11 0) +;; TRACE t2615: | | | | | | => 0 +;; TRACE t2616: | | | | | | (cc 10 1) +;; TRACE t2617: | | | | | | | (cc 10 0) +;; TRACE t2617: | | | | | | | => 0 +;; TRACE t2618: | | | | | | | (cc 9 1) +;; TRACE t2619: | | | | | | | | (cc 9 0) +;; TRACE t2619: | | | | | | | | => 0 +;; TRACE t2620: | | | | | | | | (cc 8 1) +;; TRACE t2621: | | | | | | | | | (cc 8 0) +;; TRACE t2621: | | | | | | | | | => 0 +;; TRACE t2622: | | | | | | | | | (cc 7 1) +;; TRACE t2623: | | | | | | | | | | (cc 7 0) +;; TRACE t2623: | | | | | | | | | | => 0 +;; TRACE t2624: | | | | | | | | | | (cc 6 1) +;; TRACE t2625: | | | | | | | | | | | (cc 6 0) +;; TRACE t2625: | | | | | | | | | | | => 0 +;; TRACE t2626: | | | | | | | | | | | (cc 5 1) +;; TRACE t2627: | | | | | | | | | | | | (cc 5 0) +;; TRACE t2627: | | | | | | | | | | | | => 0 +;; TRACE t2628: | | | | | | | | | | | | (cc 4 1) +;; TRACE t2629: | | | | | | | | | | | | | (cc 4 0) +;; TRACE t2629: | | | | | | | | | | | | | => 0 +;; TRACE t2630: | | | | | | | | | | | | | (cc 3 1) +;; TRACE t2631: | | | | | | | | | | | | | | (cc 3 0) +;; TRACE t2631: | | | | | | | | | | | | | | => 0 +;; TRACE t2632: | | | | | | | | | | | | | | (cc 2 1) +;; TRACE t2633: | | | | | | | | | | | | | | | (cc 2 0) +;; TRACE t2633: | | | | | | | | | | | | | | | => 0 +;; TRACE t2634: | | | | | | | | | | | | | | | (cc 1 1) +;; TRACE t2635: | | | | | | | | | | | | | | | | (cc 1 0) +;; TRACE t2635: | | | | | | | | | | | | | | | | => 0 +;; TRACE t2636: | | | | | | | | | | | | | | | | (cc 0 1) +;; TRACE t2636: | | | | | | | | | | | | | | | | => 1 +;; TRACE t2634: | | | | | | | | | | | | | | | => 1 +;; TRACE t2632: | | | | | | | | | | | | | | => 1 +;; TRACE t2630: | | | | | | | | | | | | | => 1 +;; TRACE t2628: | | | | | | | | | | | | => 1 +;; TRACE t2626: | | | | | | | | | | | => 1 +;; TRACE t2624: | | | | | | | | | | => 1 +;; TRACE t2622: | | | | | | | | | => 1 +;; TRACE t2620: | | | | | | | | => 1 +;; TRACE t2618: | | | | | | | => 1 +;; TRACE t2616: | | | | | | => 1 +;; TRACE t2614: | | | | | => 1 +;; TRACE t2637: | | | | | (cc 6 2) +;; TRACE t2638: | | | | | | (cc 6 1) +;; TRACE t2639: | | | | | | | (cc 6 0) +;; TRACE t2639: | | | | | | | => 0 +;; TRACE t2640: | | | | | | | (cc 5 1) +;; TRACE t2641: | | | | | | | | (cc 5 0) +;; TRACE t2641: | | | | | | | | => 0 +;; TRACE t2642: | | | | | | | | (cc 4 1) +;; TRACE t2643: | | | | | | | | | (cc 4 0) +;; TRACE t2643: | | | | | | | | | => 0 +;; TRACE t2644: | | | | | | | | | (cc 3 1) +;; TRACE t2645: | | | | | | | | | | (cc 3 0) +;; TRACE t2645: | | | | | | | | | | => 0 +;; TRACE t2646: | | | | | | | | | | (cc 2 1) +;; TRACE t2647: | | | | | | | | | | | (cc 2 0) +;; TRACE t2647: | | | | | | | | | | | => 0 +;; TRACE t2648: | | | | | | | | | | | (cc 1 1) +;; TRACE t2649: | | | | | | | | | | | | (cc 1 0) +;; TRACE t2649: | | | | | | | | | | | | => 0 +;; TRACE t2650: | | | | | | | | | | | | (cc 0 1) +;; TRACE t2650: | | | | | | | | | | | | => 1 +;; TRACE t2648: | | | | | | | | | | | => 1 +;; TRACE t2646: | | | | | | | | | | => 1 +;; TRACE t2644: | | | | | | | | | => 1 +;; TRACE t2642: | | | | | | | | => 1 +;; TRACE t2640: | | | | | | | => 1 +;; TRACE t2638: | | | | | | => 1 +;; TRACE t2651: | | | | | | (cc 1 2) +;; TRACE t2652: | | | | | | | (cc 1 1) +;; TRACE t2653: | | | | | | | | (cc 1 0) +;; TRACE t2653: | | | | | | | | => 0 +;; TRACE t2654: | | | | | | | | (cc 0 1) +;; TRACE t2654: | | | | | | | | => 1 +;; TRACE t2652: | | | | | | | => 1 +;; TRACE t2655: | | | | | | | (cc -4 2) +;; TRACE t2655: | | | | | | | => 0 +;; TRACE t2651: | | | | | | => 1 +;; TRACE t2637: | | | | | => 2 +;; TRACE t2613: | | | | => 3 +;; TRACE t2656: | | | | (cc 1 3) +;; TRACE t2657: | | | | | (cc 1 2) +;; TRACE t2658: | | | | | | (cc 1 1) +;; TRACE t2659: | | | | | | | (cc 1 0) +;; TRACE t2659: | | | | | | | => 0 +;; TRACE t2660: | | | | | | | (cc 0 1) +;; TRACE t2660: | | | | | | | => 1 +;; TRACE t2658: | | | | | | => 1 +;; TRACE t2661: | | | | | | (cc -4 2) +;; TRACE t2661: | | | | | | => 0 +;; TRACE t2657: | | | | | => 1 +;; TRACE t2662: | | | | | (cc -9 3) +;; TRACE t2662: | | | | | => 0 +;; TRACE t2656: | | | | => 1 +;; TRACE t2612: | | | => 4 +;; TRACE t2663: | | | (cc -14 4) +;; TRACE t2663: | | | => 0 +;; TRACE t2611: | | => 4 +;; TRACE t2664: | | (cc -39 5) +;; TRACE t2664: | | => 0 +;; TRACE t2610: | => 4 +;; TRACE t2609: => 4 +;; 4 +;; ) + + +;; TODO: orders of growth in space and number of steps. + +;; exercise 1.15: sin (x) calculation +;; a. How many times is the procedure p applied when (sine 12.15) +;; is evaluated? +;; b. What is the order of growth in space and number of steps (as +;; a function of a) used by the process generated by the sine +;; procedure when (sine a) is evaluated? +(defn cube [x] (* x x x)) + +(defn p [x] (- (* 3 x) (* 4 (cube x)))) + +(defn sine [angle] + (if (not (> (abs angle) 0.1)) + angle + (p (sine (/ angle 3.0))))) + +;; solution to (a) => 5 +;; (comment +;; user> (dotrace [p] (sine 12.15)) +;; TRACE t2490: (p 0.049999999999999996) +;; TRACE t2490: => 0.1495 +;; TRACE t2491: (p 0.1495) +;; TRACE t2491: => 0.4351345505 +;; TRACE t2492: (p 0.4351345505) +;; TRACE t2492: => 0.9758465331678772 +;; TRACE t2493: (p 0.9758465331678772) +;; TRACE t2493: => -0.7895631144708228 +;; TRACE t2494: (p -0.7895631144708228) +;; TRACE t2494: => -0.39980345741334 +;; -0.39980345741334 +;; ) + +;; solution to b +;; both space and number of steps grows as log3(a) -> log a to the base 3. +;; +;; proof: +;; a * (1/3)^n <= 0.1 +;; => take log to the base 3 on both the sides. + +;; Note: Finding the order of space in a recursive process is sort of, equiv +;; to finding the number of deferred operations. Which is in-turn the +;; same as the depth of the evaluation tree. + +;; 1.2.4: exponentiation +;; computing b^n + +;; iterative +(defn expt-iter [base counter product] + (if (= counter 0) + product + (expt-iter base + (dec counter) + (* product base)))) + +(defn myexpt [b n] + (expt-iter b n 1)) + +(defn myexpt [b n] + (if (= n 0) + 1 + (* b (myexpt b (dec n))))) + +;; fast version +(defn square [x] + (* x x)) + +(defn fast-expt [b n] + (cond (= n 0) 1 + (even? n) (square (fast-expt b (/ n 2))) + :else (* b (fast-expt b (dec n))))) + +;; exercise 1.16: +(defn myexpt [b n] + (expt-iter b n 1)) + +(defn expt-iter [b n a] + (cond (= n 0) a + (even? n) (expt-iter (square b) (/ n 2) a) + :else (expt-iter b (- n 1) (* a b)))) + +;; exercise 1.17: +(defn mult [a b] + (if (= b 0) + 0 + (+ a (mult a (- b 1))))) + +;; double +(defn twice [x] + (* 2 x)) + +(defn half [x] + (/ x 2)) + +;; product = 2 * (a * (b/2)) for even b +;; = a + (a * (b - 1)) for odd b +(defn fast-mult [a b] + (cond (= b 0) 0 + (= b 1) a + (even? b) (twice (fast-mult a (half b))) + :else (+ a (fast-mult a (- b 1))))) + +;; exercise 1.18: iterative multiply thru addition +;; the idea is to keep a state variable. +(defn fast-mult-iter [a b k] + (cond (= b 0) k + (even? b) (fast-mult-iter (twice a) (half b) k) + :else (fast-mult-iter a (- b 1) (+ k a)))) + +(defn fast-mult-new [a b] + (fast-mult-iter a b 0)) + +;; (comment +;; user> (dotrace [fast-mult-new fast-mult-iter] (fast-mult-new 2 3)) +;; TRACE t2915: (fast-mult-new 2 3) +;; TRACE t2916: | (fast-mult-iter 2 3 0) +;; TRACE t2917: | | (fast-mult-iter 2 2 2) +;; TRACE t2918: | | | (fast-mult-iter 4 1 2) +;; TRACE t2919: | | | | (fast-mult-iter 4 0 6) +;; TRACE t2919: | | | | => 6 +;; TRACE t2918: | | | => 6 +;; TRACE t2917: | | => 6 +;; TRACE t2916: | => 6 +;; TRACE t2915: => 6 +;; 6 +;; ) + +;; exercise 1.19: fast fibonacci +;; see the pdf of the notebook scan for the derivation of p' and q' +(defn ffib-iter [a b p q count] + (cond (= count 0) b + (even? count) + (ffib-iter a + b + (+ (* p p) (* q q)) + (+ (* 2 p q) (* q q)) + (/ count 2)) + :else (ffib-iter (+ (* b q) (* a q) (* a p)) + (+ (* b p) (* a q)) + p + q + (- count 1)))) + +(defn ffib [n] + (ffib-iter 1 0 0 1 n)) + +;;; Section 1.2.5: GCD +(defn mygcd [a b] + (if (= b 0) + a + (mygcd b (rem a b)))) \ No newline at end of file