From: Ramakrishnan Muthukrishnan Date: Tue, 4 May 2010 09:54:06 +0000 (+0530) Subject: namespace confusions resolved. X-Git-Url: https://git.rkrishnan.org/%5B/%5D%20/uri/%22doc.html/flags/index.php?a=commitdiff_plain;h=72cc7c9ba92d6f5668e95f00b47acd08952f371c;p=sicp.git namespace confusions resolved. --- diff --git a/src/sicp/ch1_3.clj b/src/sicp/ch1_3.clj new file mode 100644 index 0000000..0cf7b28 --- /dev/null +++ b/src/sicp/ch1_3.clj @@ -0,0 +1,43 @@ + +(ns sicp.ch1-3 + (:use [sicp utils] + [clojure.contrib test-is])) + +;; 1.3.1: Procedures as arguments +(defn sum-integers [a b] + (if (> a b) + 0 + (+ a (sum-integers (+ a 1) b)))) + +(defn sum-cubes [a b] + (if (> a b) + 0 + (+ (cube a) (sum-cubes (+ a 1) b)))) + +(defn pi-sum [a b] + (if (> a b) + 0 + (+ (/ 1.0 (* a (+ a 2))) (pi-sum (+ a 1) b)))) + +(defn sum [term a next b] + (if (> a b) + 0 + (+ (term a) + (sum term (next a) next b)))) + +(def sum-cubes-new (fn[a b] (sum cube a inc b))) + +(deftest test-sum-of-first-10-integers + (is (sum #(identity %) 1 inc 10) 55)) + +;; (* (sum #(/ 1.0 (* % (+ % 2))) 1 #(+ % 4) 1000) 8) +;;=> 3.139592655589783 (approaches PI) + +(defn integral [f a b dx] + (* (sum f (+ a (/ dx 2)) #(+ % dx) b) + dx)) + +(integral cube 0 1 0.001) +;;=>0.249999875000001 +(integral cube 0 1 0.005) +;;=>0.24999687500000028 \ No newline at end of file diff --git a/src/sicp/ex1_1.clj b/src/sicp/ex1_1.clj new file mode 100644 index 0000000..ad9b8de --- /dev/null +++ b/src/sicp/ex1_1.clj @@ -0,0 +1,27 @@ +(ns sicp.ex1_1 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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 diff --git a/src/sicp/ex1_10.clj b/src/sicp/ex1_10.clj new file mode 100644 index 0000000..413e30c --- /dev/null +++ b/src/sicp/ex1_10.clj @@ -0,0 +1,36 @@ +(ns sicp.ex1_10 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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) diff --git a/src/sicp/ex1_11.clj b/src/sicp/ex1_11.clj new file mode 100644 index 0000000..d76c807 --- /dev/null +++ b/src/sicp/ex1_11.clj @@ -0,0 +1,48 @@ +(ns sicp.ex1_11 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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)))) diff --git a/src/sicp/ex1_12.clj b/src/sicp/ex1_12.clj new file mode 100644 index 0000000..ff3e39a --- /dev/null +++ b/src/sicp/ex1_12.clj @@ -0,0 +1,22 @@ +(ns sicp.ex1_12 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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)))))) diff --git a/src/sicp/ex1_13.clj b/src/sicp/ex1_13.clj new file mode 100644 index 0000000..e9b1fd7 --- /dev/null +++ b/src/sicp/ex1_13.clj @@ -0,0 +1,18 @@ +(ns sicp.ex1_13 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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) +;; ) diff --git a/src/sicp/ex1_14.clj b/src/sicp/ex1_14.clj new file mode 100644 index 0000000..a3df2aa --- /dev/null +++ b/src/sicp/ex1_14.clj @@ -0,0 +1,133 @@ +(ns sicp.ex1_14 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; exercise 1.14: tree of (count-changes 11) +(comment + See the notebook (sorry, don't have the time to scan it and put it on the web) + 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. diff --git a/src/sicp/ex1_15.clj b/src/sicp/ex1_15.clj new file mode 100644 index 0000000..11249f5 --- /dev/null +++ b/src/sicp/ex1_15.clj @@ -0,0 +1,43 @@ +(ns sicp.ex1_15 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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 p [x] (- (* 3 x) (* 4 (cube x)))) + +(defn sine [angle] + (if (not (> (myabs 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. diff --git a/src/sicp/ex1_16.clj b/src/sicp/ex1_16.clj new file mode 100644 index 0000000..9bc774a --- /dev/null +++ b/src/sicp/ex1_16.clj @@ -0,0 +1,12 @@ +(ns sicp.ex1_16 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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)))) diff --git a/src/sicp/ex1_17.clj b/src/sicp/ex1_17.clj new file mode 100644 index 0000000..ac057e0 --- /dev/null +++ b/src/sicp/ex1_17.clj @@ -0,0 +1,18 @@ +(ns sicp.ex1_17 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; exercise 1.17: +(defn mult [a b] + (if (= b 0) + 0 + (+ a (mult a (- b 1))))) + +;; double +;; 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))))) diff --git a/src/sicp/ex1_18.clj b/src/sicp/ex1_18.clj new file mode 100644 index 0000000..7e45dd1 --- /dev/null +++ b/src/sicp/ex1_18.clj @@ -0,0 +1,28 @@ +(ns sicp.ex1_18 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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 +;; ) diff --git a/src/sicp/ex1_19.clj b/src/sicp/ex1_19.clj new file mode 100644 index 0000000..06ab367 --- /dev/null +++ b/src/sicp/ex1_19.clj @@ -0,0 +1,22 @@ +(ns sicp.ex1_19 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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/ex1_2.clj b/src/sicp/ex1_2.clj new file mode 100644 index 0000000..2fae959 --- /dev/null +++ b/src/sicp/ex1_2.clj @@ -0,0 +1,7 @@ +(ns sicp.ex1_2 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; exercise 1.2: Translate the given expression into prefix form +(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 1 5))))) + (* 3 (- 6 2) (- 2 7))) ; -71/300 diff --git a/src/sicp/ex1_20.clj b/src/sicp/ex1_20.clj new file mode 100644 index 0000000..a7d0a62 --- /dev/null +++ b/src/sicp/ex1_20.clj @@ -0,0 +1,10 @@ +(ns sicp.ex1_20 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;;; exercise 1.20. +;; +;; normal order - 18, applicative order - 4. +;; +;; too lazy to scan things from the notebook. May be I should instead +;; use a wiki. diff --git a/src/sicp/ex1_21.clj b/src/sicp/ex1_21.clj new file mode 100644 index 0000000..af6d91b --- /dev/null +++ b/src/sicp/ex1_21.clj @@ -0,0 +1,13 @@ +(ns sicp.ex1_21 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; exercise 1.21 +(comment +user> (smallest-divisor 199) +199 +user> (smallest-divisor 1999) +1999 +user> (smallest-divisor 19999) +7 +) diff --git a/src/sicp/ex1_22.clj b/src/sicp/ex1_22.clj new file mode 100644 index 0000000..daf7815 --- /dev/null +++ b/src/sicp/ex1_22.clj @@ -0,0 +1,112 @@ +(ns sicp.ex1_22 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; exercise 1.22 +(defn timed-prime-test [n] + (prn) + (print n) + (start-prime-test n (System/nanoTime))) + +(defn start-prime-test [n start-time] + (if (prime? n) + (report-prime (- (System/nanoTime) start-time)))) + +(defn report-prime [elapsed-time] + (print " *** ") + (print elapsed-time)) + +(defn search-for-primes [a b] + (cond (>= a b) nil + (even? a) (search-for-primes (+ 1 a) b) + (timed-prime-test a) (search-for-primes (+ 2 a) b) + :else (search-for-primes (+ 2 a) b))) + +;;; three smallest primes greater than 1000 +;;; 1009, 1013, 1019 +(take 3 (filter #(prime? %) (iterate inc 1000))) +;=> (1009 1013 1019) + +;=> 0.9642028750000001 + +;;; > 10,000: 10007, 10009, 10037 +(take 3 (filter #(prime? %) (iterate inc 10000))) +;=> (10007 10009 10037) + +;=> 1.5897884999999998 + +;;; > 100,000: 100003, 100019, 100043 +(take 3 (filter #(prime? %) (iterate inc 100000))) +;=> (100003 100019 100043) + +;=> 1.8525091250000003 + +;;; > 1,000,000: 1000003, 1000033, 1000037 +(take 3 (filter #(prime? %) (iterate inc 1000000))) +;=> (1000003 1000033 1000037) + +;=> 1.908832125 + +;; time taken seem to increase as the range increases. +;; but they are totally random on the jvm, so I can't find +;; the exact relation. + +(comment +user> (microbench 10 (take 3 (filter #(prime? %) (iterate inc 1000)))) +Warming up! +Benchmarking... +(1009 1013 1019) +(1009 1013 1019) +(1009 1013 1019) +(1009 1013 1019) +(1009 1013 1019) +(1009 1013 1019) +(1009 1013 1019) +(1009 1013 1019) +(1009 1013 1019) +(1009 1013 1019) +Total runtime: 0.28404500000000005 +Highest time : 0.083949 +Lowest time : 0.019416 +Average : 0.022585000000000008 +(0.083949 0.019416 0.023257 0.020394 0.024165 0.024514 0.024374 0.020813 0.021721 0.021442) +user> (microbench 10 (take 3 (filter #(prime? %) (iterate inc 10000)))) +Warming up! +Benchmarking... +(10007 10009 10037) +(10007 10009 10037) +(10007 10009 10037) +(10007 10009 10037) +(10007 10009 10037) +(10007 10009 10037) +(10007 10009 10037) +(10007 10009 10037) +(10007 10009 10037) +(10007 10009 10037) +Total runtime: 0.26462800000000003 +Highest time : 0.067118 +Lowest time : 0.020533 +Average : 0.022122125000000006 +(0.067118 0.022698 0.024095 0.023537 0.020533 0.020882 0.020603 0.021372 0.020603 0.023187) +user> (microbench 10 (take 3 (filter #(prime? %) (iterate inc 100000)))) +Warming up! +Benchmarking... +(100003 100019 100043) +(100003 100019 100043) +(100003 100019 100043) +(100003 100019 100043) +(100003 100019 100043) +(100003 100019 100043) +(100003 100019 100043) +(100003 100019 100043) +(100003 100019 100043) +(100003 100019 100043) +Total runtime: 0.265118 +Highest time : 0.073263 +Lowest time : 0.020254 +Average : 0.021450125000000004 +(0.073263 0.023048 0.023467 0.021022 0.020394 0.020254 0.021302 0.020812 0.020743 0.020813) +) + +;;; can't make out any sqrt(10) relation between the numbers. may be because +;;; jvm compilation is doing some behind the scene tricks. diff --git a/src/sicp/ex1_23.clj b/src/sicp/ex1_23.clj new file mode 100644 index 0000000..8200ecf --- /dev/null +++ b/src/sicp/ex1_23.clj @@ -0,0 +1,19 @@ +(ns sicp.ex1_23 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;;; exercise 1.23 +(defn next-divisor [n] + (if (= n 2) + 3 + (+ n 2))) + + +(defn find-divisor [n test-divisor] + (cond (> (square test-divisor) n) n + (divides? test-divisor n) test-divisor + :else (find-divisor n (next-divisor test-divisor)))) + +(comment + I can't see any noticable difference in the speed. +) diff --git a/src/sicp/ex1_24.clj b/src/sicp/ex1_24.clj new file mode 100644 index 0000000..ddffc11 --- /dev/null +++ b/src/sicp/ex1_24.clj @@ -0,0 +1,10 @@ +(ns sicp.ex1_24 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;;; exercise 1.24 +(comment + (microbench 10 (take 3 (filter #(fast-prime? %) (iterate inc 1000)))) + ... + "I did not observe any difference". +) diff --git a/src/sicp/ex1_25.clj b/src/sicp/ex1_25.clj new file mode 100644 index 0000000..8dfd0fc --- /dev/null +++ b/src/sicp/ex1_25.clj @@ -0,0 +1,17 @@ +(ns sicp.ex1_25 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; exercise 1.25 +(defn expmod [base exp m] + (rem (fast-expt base exp) m)) + +(comment + In the case of the original expmod implementation, square and remainder + calls are interspersed, so square always deals with a small number, whereas + with the above way, we do a series of squaring and then in the end take + remainder. Squaring of big numbers are very inefficient as the CPU has to + do multi-byte arithmetic which consumes many cycles. + + So the new version is several times slower than the original. +) diff --git a/src/sicp/ex1_26.clj b/src/sicp/ex1_26.clj new file mode 100644 index 0000000..cd1ba73 --- /dev/null +++ b/src/sicp/ex1_26.clj @@ -0,0 +1,12 @@ +(ns sicp.ex1_26 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;;; exercise 1.26 +(comment + "Instead of calling (square x), Louis now makes does (* x x). In the former, + case, x is evaluated only once, where as in the second, x gets evaluated + 2x, 4x, 8x, 16x and so on (for any x which is recursive). So, if the original + computation is considered T(log_n), then the new process T(n). This can also + be illustrated with the call tree." +) diff --git a/src/sicp/ex1_27.clj b/src/sicp/ex1_27.clj new file mode 100644 index 0000000..e0c02e1 --- /dev/null +++ b/src/sicp/ex1_27.clj @@ -0,0 +1,34 @@ +(ns sicp.ex1_27 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; exercise 1.27 +(comment + "Some notes on Carmichael numbers: Carmichael numbers are those that fail + Fermat little test. That is, for any n in the Carmichael set, + (prime? n) => false + (fermat-test n) => true." + ) +(defn brute-force-fermat-test [n] + (try-all 2 n)) + +(defn try-all [a n] + (cond (= a n) true + (try-it a n) (try-all (inc a) n) + :else false)) +(comment + "all the given numbers pass the above test, i.e. for every a < n, + a^n mod n === a mod n" + user> (brute-force-fermat-test 561) + true + user> (brute-force-fermat-test 1105) + true + user> (brute-force-fermat-test 1729) + true + user> (brute-force-fermat-test 2465) + true + user> (brute-force-fermat-test 2821) + true + user> (brute-force-fermat-test 6601) + true + ) diff --git a/src/sicp/ex1_28.clj b/src/sicp/ex1_28.clj new file mode 100644 index 0000000..0a8e1f1 --- /dev/null +++ b/src/sicp/ex1_28.clj @@ -0,0 +1,30 @@ +(ns sicp.ex1_28 + (:use [sicp utils] + [clojure.contrib trace test-is])) + + +;;; exercise 1.28 +(defn expmod2 [base exp m] + (cond (= exp 0) 1 + (even? exp) (square-test (expmod2 base (/ exp 2) m) m) + :else (rem (* base (expmod2 base (dec exp) m)) + m))) + +(defn square-test [x m] + (if (and (not (or (= x 1) (= x (- m 1)))) + (= (rem (square x) m) 1)) + 0 + (rem (square x) m))) + +(defn miller-rabin-test [n] + (try-it (+ 2 (rand-int (- n 2))) + n)) + +(defn try-it [a n] + (= (expmod2 a (- n 1) n) 1)) + +(comment + "If the random number generated (a) is 1, then this returns false + positives. So generate random numbers between 2 and n-1. (is this + assumption correct?) " +) \ No newline at end of file diff --git a/src/sicp/ex1_29.clj b/src/sicp/ex1_29.clj new file mode 100644 index 0000000..33a3458 --- /dev/null +++ b/src/sicp/ex1_29.clj @@ -0,0 +1,28 @@ +(ns sicp.ex1_29 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; simpson's rule of integration +(defn sum [term a next b] + (if (> a b) + 0 + (+ (term a) + (sum term (next a) next b)))) + +(defn make-fac [k n] + (cond (= k 0) 1 + (= k n) 1 + (even? k) 2 + :else 4)) + +(defn simpson-sum [term a next-fn b n k] + (let [fac (make-fac k n)] + (if (> k n) + 0 + (+ (* fac (term a)) + (simpson-sum term (next-fn a) next-fn b n (+ k 1)))))) + +(defn simpson-rule [f a b n] + (let [h (/ (- b a) n)] + (* (simpson-sum f a #(+ h %) b n 0) + (/ h 3.0)))) diff --git a/src/sicp/ex1_3.clj b/src/sicp/ex1_3.clj new file mode 100644 index 0000000..b7e70b2 --- /dev/null +++ b/src/sicp/ex1_3.clj @@ -0,0 +1,25 @@ +(ns sicp.ex1_3 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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)))) diff --git a/src/sicp/ex1_4.clj b/src/sicp/ex1_4.clj new file mode 100644 index 0000000..2d8e0bd --- /dev/null +++ b/src/sicp/ex1_4.clj @@ -0,0 +1,15 @@ +(ns sicp.ex1_4 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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. + ) diff --git a/src/sicp/ex1_5.clj b/src/sicp/ex1_5.clj new file mode 100644 index 0000000..9638b3b --- /dev/null +++ b/src/sicp/ex1_5.clj @@ -0,0 +1,30 @@ +(ns sicp.ex1_5 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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. + ) diff --git a/src/sicp/ex1_6.clj b/src/sicp/ex1_6.clj new file mode 100644 index 0000000..5144f1b --- /dev/null +++ b/src/sicp/ex1_6.clj @@ -0,0 +1,29 @@ +(ns sicp.ex1_6 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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.) diff --git a/src/sicp/ex1_7.clj b/src/sicp/ex1_7.clj new file mode 100644 index 0000000..f79dae6 --- /dev/null +++ b/src/sicp/ex1_7.clj @@ -0,0 +1,54 @@ +(ns sicp.ex1_7 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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 + ) \ No newline at end of file diff --git a/src/sicp/ex1_8.clj b/src/sicp/ex1_8.clj new file mode 100644 index 0000000..bdf2e05 --- /dev/null +++ b/src/sicp/ex1_8.clj @@ -0,0 +1,30 @@ +(ns sicp.ex1_8 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; exercise 1.8: cube root +(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> +) diff --git a/src/sicp/ex1_9.clj b/src/sicp/ex1_9.clj new file mode 100644 index 0000000..4029985 --- /dev/null +++ b/src/sicp/ex1_9.clj @@ -0,0 +1,48 @@ +(ns sicp.ex1_9 + (:use [sicp utils] + [clojure.contrib trace test-is])) + +;; 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 +;; )