--- /dev/null
+
+(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
--- /dev/null
+(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
--- /dev/null
+(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)
--- /dev/null
+(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))))
--- /dev/null
+(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))))))
--- /dev/null
+(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)
+;; )
--- /dev/null
+(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.
--- /dev/null
+(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.
--- /dev/null
+(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))))
--- /dev/null
+(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)))))
--- /dev/null
+(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
+;; )
--- /dev/null
+(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))
--- /dev/null
+(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
--- /dev/null
+(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.
--- /dev/null
+(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
+)
--- /dev/null
+(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.
--- /dev/null
+(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.
+)
--- /dev/null
+(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".
+)
--- /dev/null
+(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.
+)
--- /dev/null
+(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."
+)
--- /dev/null
+(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
+ )
--- /dev/null
+(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
--- /dev/null
+(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))))
--- /dev/null
+(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))))
--- /dev/null
+(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.
+ )
--- /dev/null
+(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.
+ )
--- /dev/null
+(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.)
--- /dev/null
+(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
--- /dev/null
+(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>
+)
--- /dev/null
+(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
+;; )