]> git.rkrishnan.org Git - sicp.git/blob - src/sicp/ch1_2.clj
Solution to exercise 1.28. Please look at the comments and see if my
[sicp.git] / src / sicp / ch1_2.clj
1 (ns sicp.ch1-2
2   (:use [sicp utils]
3         [clojure.contrib.math :only (sqrt expt)]
4         [clojure.contrib.trace :only (dotrace)]))
5
6
7 (defn factorial [n]
8   (if (= n 1)
9     1
10     (* n (factorial (- n 1)))))
11
12 ;; stack friendly version
13 (defn factorial2 [n]
14   (loop [x n acc 1] 
15     (if (= x 1)
16       acc
17       (recur (- x 1) (* acc x)))))
18
19 ;; even better
20 (defn factorial3 [n]
21   (reduce * (range 1 (inc n))))
22
23 ;; (comment
24 ;;  user> (dotrace [factorial] (factorial 3))
25 ;;  TRACE t2701: (factorial 3)
26 ;;  TRACE t2702: |    (factorial 2)
27 ;;  TRACE t2703: |    |    (factorial 1)
28 ;;  TRACE t2703: |    |    => 1
29 ;;  TRACE t2702: |    => 2
30 ;;  TRACE t2701: => 6
31 ;;  6
32 ;; )
33
34 ;; (comment
35 ;;   sicp.chapter1.ch1_2> (dotrace [factorial] (factorial 6))
36 ;;   TRACE t2778: (factorial 6)
37 ;;   TRACE t2779: |    (factorial 5)
38 ;;   TRACE t2780: |    |    (factorial 4)
39 ;;   TRACE t2781: |    |    |    (factorial 3)
40 ;;   TRACE t2782: |    |    |    |    (factorial 2)
41 ;;   TRACE t2783: |    |    |    |    |    (factorial 1)
42 ;;   TRACE t2783: |    |    |    |    |    => 1
43 ;;   TRACE t2782: |    |    |    |    => 2
44 ;;   TRACE t2781: |    |    |    => 6
45 ;;   TRACE t2780: |    |    => 24
46 ;;   TRACE t2779: |    => 120
47 ;;   TRACE t2778: => 720
48 ;;   720
49 ;;   )
50
51 ;; (comment
52 ;;   sicp.chapter1.ch1_2> (dotrace [factorial2] (factorial2 6))
53 ;;   TRACE t2806: (factorial2 6)
54 ;;   TRACE t2806: => 720
55 ;;   720
56 ;;   )
57
58 (defn fact-iter [product counter max-count]
59   (if (> counter max-count)
60     product
61     (fact-iter (* product counter)
62                (inc counter)
63                max-count)))
64
65 (defn factorial [n]
66   (fact-iter 1 1 n))
67
68 ;; (comment
69 ;; user> (dotrace [factorial fact-iter] (factorial 6))
70 ;; TRACE t2378: (factorial 6)
71 ;; TRACE t2379: |    (fact-iter 1 1 6)
72 ;; TRACE t2380: |    |    (fact-iter 1 2 6)
73 ;; TRACE t2381: |    |    |    (fact-iter 2 3 6)
74 ;; TRACE t2382: |    |    |    |    (fact-iter 6 4 6)
75 ;; TRACE t2383: |    |    |    |    |    (fact-iter 24 5 6)
76 ;; TRACE t2384: |    |    |    |    |    |    (fact-iter 120 6 6)
77 ;; TRACE t2385: |    |    |    |    |    |    |    (fact-iter 720 7 6)
78 ;; TRACE t2385: |    |    |    |    |    |    |    => 720
79 ;; TRACE t2384: |    |    |    |    |    |    => 720
80 ;; TRACE t2383: |    |    |    |    |    => 720
81 ;; TRACE t2382: |    |    |    |    => 720
82 ;; TRACE t2381: |    |    |    => 720
83 ;; TRACE t2380: |    |    => 720
84 ;; TRACE t2379: |    => 720
85 ;; TRACE t2378: => 720
86 ;; 720
87 ;; )
88
89 ;; observation: clojure loop-recur construct is essentially the same as
90 ;; the iterative version.
91
92 ;; exercise 1.9
93 (defn ++ [a b]
94   (if (= a 0)
95     b
96     (inc (++ (dec a) b))))
97
98 ;; (comment
99 ;;   This version is a recursive process, where the previous call increments
100 ;;   the sum by 1 and each call decrement the first operand by 1.
101   
102 ;; user> (dotrace [++] (++ 4 5))
103 ;; TRACE t3745: (++ 4 5)
104 ;; TRACE t3746: |    (++ 3 5)
105 ;; TRACE t3747: |    |    (++ 2 5)
106 ;; TRACE t3748: |    |    |    (++ 1 5)
107 ;; TRACE t3749: |    |    |    |    (++ 0 5)
108 ;; TRACE t3749: |    |    |    |    => 5
109 ;; TRACE t3748: |    |    |    => 6
110 ;; TRACE t3747: |    |    => 7
111 ;; TRACE t3746: |    => 8
112 ;; TRACE t3745: => 9
113 ;; 9
114 ;; )
115
116 (defn ++ [a b]
117   (if (= a 0)
118     b
119     (++ (dec a) (inc b))))
120
121 ;; (comment
122   
123 ;; user> (dotrace [++] (++ 4 5))
124 ;; TRACE t3766: (++ 4 5)
125 ;; TRACE t3767: |    (++ 3 6)
126 ;; TRACE t3768: |    |    (++ 2 7)
127 ;; TRACE t3769: |    |    |    (++ 1 8)
128 ;; TRACE t3770: |    |    |    |    (++ 0 9)
129 ;; TRACE t3770: |    |    |    |    => 9
130 ;; TRACE t3769: |    |    |    => 9
131 ;; TRACE t3768: |    |    => 9
132 ;; TRACE t3767: |    => 9
133 ;; TRACE t3766: => 9
134 ;; 9
135 ;; )
136
137 ;; exercise 1.10
138 ;; ackerman functions
139 (defn A [x y]
140   (cond (= y 0) 0
141         (= x 0) (* 2 y)
142         (= y 1) 2
143         :else (A (- x 1)
144                  (A x (- y 1)))))
145
146 ;; (comment
147 ;; user> (A 1 10)
148 ;; 1024
149 ;; user> (A 2 4)
150 ;; 65536
151 ;; user> (A 3 3)
152 ;; 65536
153 ;; )
154
155 (defn f [n] (A 0 n)) ; f(n) = 2n
156 (defn g [n] (A 1 n)) ; g(n) = 2^n
157 ;; (comment
158 ;;   g (n) = A (1,n)
159 ;;         = A (0, A (1, n-1)) = f (A(1,n-1))
160 ;;        = f (f (1,n-2)) 
161 ;;          .....
162 ;;          = f (f (f ... f (1,(n- (n-1)))))
163 ;;            = f (f (f ... 2))
164 ;;              = 2 * (2^(n-1))
165 ;;                = 2^n
166 ;; )
167
168 (defn h [n] (A 2 n)) ; h(n) = 2^(n^2)
169
170 ;; section 1.2.2: Tree Recursion
171 (defn fib [n]
172   (cond (= n 0) 0
173         (= n 1) 1
174         :else (+ (fib (- n 1))
175                  (fib (- n 2)))))
176
177 ;; iterative version
178 (defn fib-iter [a b count]
179   (if (= count 0)
180     b
181     (fib-iter (+ a b) a (dec count))))
182
183 (defn fib [n]
184   (fib-iter 1 0 n))
185
186 ;; example: counting changes
187 (defn first-denomination [kinds-of-coins]
188   (cond (= kinds-of-coins 1) 1
189         (= kinds-of-coins 2) 5
190         (= kinds-of-coins 3) 10
191         (= kinds-of-coins 4) 25
192         (= kinds-of-coins 5) 50))
193
194
195 (defn first-denomination [kinds-of-coins]
196   ({1 1 2 5 3 10 4 25 5 50} kinds-of-coins))
197
198 (defn cc [amount kinds-of-coins]
199   (cond (= amount 0) 1
200         (or (< amount 0) (= kinds-of-coins 0)) 0
201         :else (+ (cc amount (- kinds-of-coins 1))
202                  (cc (- amount
203                         (first-denomination kinds-of-coins))
204                      kinds-of-coins))))
205
206 (defn count-change [amount]
207   (cc amount 5))
208
209 ;; exercise 1.11: A function f is defined by the rule that f(n) = n if n < 3
210 ;;                and f(n) = f(n - 1) + 2f(n  - 2) + 3f(n - 3) if n> 3.
211 ;;                Write a procedure that computes f by means of a recursive
212 ;;                process. Write a procedure that computes f by means of an
213 ;;                iterative process. 
214 (defn f [n]
215   (if (< n 3)
216     n
217     (+ (f (- n 1))
218        (* 2 (f (- n 2)))
219        (* 3 (f (- n 3))))))
220
221 ;; (comment
222 ;; user> (map f (range 10))
223 ;; (0 1 2 4 11 25 59 142 335 796)  
224 ;; )
225
226 ;; ex 1.11: iterative version
227 (defn f-iter [count prev0 prev1 prev2]
228   (if (= count 3)
229     (+ prev0
230        (* 2 prev1)
231        (* 3 prev2))
232     (f-iter (dec count)
233             (+ prev0
234                (* 2 prev1)
235                (* 3 prev2))
236             prev0
237             prev1)))
238
239 (defn f [n]
240   (if (< n 3)
241     n
242     (f-iter n 2 1 0)))
243
244 ;; ex 1.11: iterative version with let
245 (defn f-iter [count prev0 prev1 prev2]
246   (let [res (+ prev0 (* 2 prev1) (* 3 prev2))]
247     (if (= count 3)
248       res
249       (f-iter (dec count)
250               res
251               prev0
252               prev1))))
253
254 ;; exercise 1.12.  The following pattern of numbers is called Pascal's triangle.
255 ;;          1
256 ;;        1   1
257 ;;      1   2   1
258 ;;    1   3   3   1
259 ;;  1   4   6   4   1
260 ;; ...................
261 ;;
262 ;;                 The numbers at the edge of the triangle are all 1, and each
263 ;;                 number inside the triangle is the sum of the two numbers above
264 ;;                 it. Write a procedure that computes elements of Pascal's triangle
265 ;;                 by means of a recursive process. 
266 (defn pascal [row col]
267   (when (<= col row)
268     (if (or (= col 0) (= row col))
269       1
270       (+ (pascal (dec row) col)
271          (pascal (dec row) (dec col))))))
272
273 ;; exercise 1.13:
274 (comment
275 See the pdfs in the directory for the answers.
276 )
277
278 ;; ex 1.13 (contd)
279 (defn fib-approx [n]
280   (let [phi (/ (+ 1 (sqrt 5)) 2)]
281     (/ (expt phi n) (sqrt 5))))
282
283 ;; (comment
284 ;; user> (map fib-approx (range 10))
285 ;; (0.4472135954999579 0.7236067977499789 1.1708203932499368 1.8944271909999157 3.065247584249853 4.959674775249769 8.024922359499623 12.984597134749393 21.009519494249016 33.99411662899841)
286 ;; )
287
288 ;; exercise 1.14: tree of (count-changes 11)
289 (comment
290   See the pdf for the tree representation.
291 )
292
293
294 ;; order of size and computation
295 ;; see PDF, but below is the trace tree.
296 ;; (comment
297 ;; user> (use 'clojure.contrib.trace)
298 ;; nil
299 ;; user> (dotrace [count-change cc] (count-change 11))
300 ;; TRACE t2609: (count-change 11)
301 ;; TRACE t2610: |    (cc 11 5)
302 ;; TRACE t2611: |    |    (cc 11 4)
303 ;; TRACE t2612: |    |    |    (cc 11 3)
304 ;; TRACE t2613: |    |    |    |    (cc 11 2)
305 ;; TRACE t2614: |    |    |    |    |    (cc 11 1)
306 ;; TRACE t2615: |    |    |    |    |    |    (cc 11 0)
307 ;; TRACE t2615: |    |    |    |    |    |    => 0
308 ;; TRACE t2616: |    |    |    |    |    |    (cc 10 1)
309 ;; TRACE t2617: |    |    |    |    |    |    |    (cc 10 0)
310 ;; TRACE t2617: |    |    |    |    |    |    |    => 0
311 ;; TRACE t2618: |    |    |    |    |    |    |    (cc 9 1)
312 ;; TRACE t2619: |    |    |    |    |    |    |    |    (cc 9 0)
313 ;; TRACE t2619: |    |    |    |    |    |    |    |    => 0
314 ;; TRACE t2620: |    |    |    |    |    |    |    |    (cc 8 1)
315 ;; TRACE t2621: |    |    |    |    |    |    |    |    |    (cc 8 0)
316 ;; TRACE t2621: |    |    |    |    |    |    |    |    |    => 0
317 ;; TRACE t2622: |    |    |    |    |    |    |    |    |    (cc 7 1)
318 ;; TRACE t2623: |    |    |    |    |    |    |    |    |    |    (cc 7 0)
319 ;; TRACE t2623: |    |    |    |    |    |    |    |    |    |    => 0
320 ;; TRACE t2624: |    |    |    |    |    |    |    |    |    |    (cc 6 1)
321 ;; TRACE t2625: |    |    |    |    |    |    |    |    |    |    |    (cc 6 0)
322 ;; TRACE t2625: |    |    |    |    |    |    |    |    |    |    |    => 0
323 ;; TRACE t2626: |    |    |    |    |    |    |    |    |    |    |    (cc 5 1)
324 ;; TRACE t2627: |    |    |    |    |    |    |    |    |    |    |    |    (cc 5 0)
325 ;; TRACE t2627: |    |    |    |    |    |    |    |    |    |    |    |    => 0
326 ;; TRACE t2628: |    |    |    |    |    |    |    |    |    |    |    |    (cc 4 1)
327 ;; TRACE t2629: |    |    |    |    |    |    |    |    |    |    |    |    |    (cc 4 0)
328 ;; TRACE t2629: |    |    |    |    |    |    |    |    |    |    |    |    |    => 0
329 ;; TRACE t2630: |    |    |    |    |    |    |    |    |    |    |    |    |    (cc 3 1)
330 ;; TRACE t2631: |    |    |    |    |    |    |    |    |    |    |    |    |    |    (cc 3 0)
331 ;; TRACE t2631: |    |    |    |    |    |    |    |    |    |    |    |    |    |    => 0
332 ;; TRACE t2632: |    |    |    |    |    |    |    |    |    |    |    |    |    |    (cc 2 1)
333 ;; TRACE t2633: |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    (cc 2 0)
334 ;; TRACE t2633: |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    => 0
335 ;; TRACE t2634: |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    (cc 1 1)
336 ;; TRACE t2635: |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    (cc 1 0)
337 ;; TRACE t2635: |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    => 0
338 ;; TRACE t2636: |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    (cc 0 1)
339 ;; TRACE t2636: |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    => 1
340 ;; TRACE t2634: |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    => 1
341 ;; TRACE t2632: |    |    |    |    |    |    |    |    |    |    |    |    |    |    => 1
342 ;; TRACE t2630: |    |    |    |    |    |    |    |    |    |    |    |    |    => 1
343 ;; TRACE t2628: |    |    |    |    |    |    |    |    |    |    |    |    => 1
344 ;; TRACE t2626: |    |    |    |    |    |    |    |    |    |    |    => 1
345 ;; TRACE t2624: |    |    |    |    |    |    |    |    |    |    => 1
346 ;; TRACE t2622: |    |    |    |    |    |    |    |    |    => 1
347 ;; TRACE t2620: |    |    |    |    |    |    |    |    => 1
348 ;; TRACE t2618: |    |    |    |    |    |    |    => 1
349 ;; TRACE t2616: |    |    |    |    |    |    => 1
350 ;; TRACE t2614: |    |    |    |    |    => 1
351 ;; TRACE t2637: |    |    |    |    |    (cc 6 2)
352 ;; TRACE t2638: |    |    |    |    |    |    (cc 6 1)
353 ;; TRACE t2639: |    |    |    |    |    |    |    (cc 6 0)
354 ;; TRACE t2639: |    |    |    |    |    |    |    => 0
355 ;; TRACE t2640: |    |    |    |    |    |    |    (cc 5 1)
356 ;; TRACE t2641: |    |    |    |    |    |    |    |    (cc 5 0)
357 ;; TRACE t2641: |    |    |    |    |    |    |    |    => 0
358 ;; TRACE t2642: |    |    |    |    |    |    |    |    (cc 4 1)
359 ;; TRACE t2643: |    |    |    |    |    |    |    |    |    (cc 4 0)
360 ;; TRACE t2643: |    |    |    |    |    |    |    |    |    => 0
361 ;; TRACE t2644: |    |    |    |    |    |    |    |    |    (cc 3 1)
362 ;; TRACE t2645: |    |    |    |    |    |    |    |    |    |    (cc 3 0)
363 ;; TRACE t2645: |    |    |    |    |    |    |    |    |    |    => 0
364 ;; TRACE t2646: |    |    |    |    |    |    |    |    |    |    (cc 2 1)
365 ;; TRACE t2647: |    |    |    |    |    |    |    |    |    |    |    (cc 2 0)
366 ;; TRACE t2647: |    |    |    |    |    |    |    |    |    |    |    => 0
367 ;; TRACE t2648: |    |    |    |    |    |    |    |    |    |    |    (cc 1 1)
368 ;; TRACE t2649: |    |    |    |    |    |    |    |    |    |    |    |    (cc 1 0)
369 ;; TRACE t2649: |    |    |    |    |    |    |    |    |    |    |    |    => 0
370 ;; TRACE t2650: |    |    |    |    |    |    |    |    |    |    |    |    (cc 0 1)
371 ;; TRACE t2650: |    |    |    |    |    |    |    |    |    |    |    |    => 1
372 ;; TRACE t2648: |    |    |    |    |    |    |    |    |    |    |    => 1
373 ;; TRACE t2646: |    |    |    |    |    |    |    |    |    |    => 1
374 ;; TRACE t2644: |    |    |    |    |    |    |    |    |    => 1
375 ;; TRACE t2642: |    |    |    |    |    |    |    |    => 1
376 ;; TRACE t2640: |    |    |    |    |    |    |    => 1
377 ;; TRACE t2638: |    |    |    |    |    |    => 1
378 ;; TRACE t2651: |    |    |    |    |    |    (cc 1 2)
379 ;; TRACE t2652: |    |    |    |    |    |    |    (cc 1 1)
380 ;; TRACE t2653: |    |    |    |    |    |    |    |    (cc 1 0)
381 ;; TRACE t2653: |    |    |    |    |    |    |    |    => 0
382 ;; TRACE t2654: |    |    |    |    |    |    |    |    (cc 0 1)
383 ;; TRACE t2654: |    |    |    |    |    |    |    |    => 1
384 ;; TRACE t2652: |    |    |    |    |    |    |    => 1
385 ;; TRACE t2655: |    |    |    |    |    |    |    (cc -4 2)
386 ;; TRACE t2655: |    |    |    |    |    |    |    => 0
387 ;; TRACE t2651: |    |    |    |    |    |    => 1
388 ;; TRACE t2637: |    |    |    |    |    => 2
389 ;; TRACE t2613: |    |    |    |    => 3
390 ;; TRACE t2656: |    |    |    |    (cc 1 3)
391 ;; TRACE t2657: |    |    |    |    |    (cc 1 2)
392 ;; TRACE t2658: |    |    |    |    |    |    (cc 1 1)
393 ;; TRACE t2659: |    |    |    |    |    |    |    (cc 1 0)
394 ;; TRACE t2659: |    |    |    |    |    |    |    => 0
395 ;; TRACE t2660: |    |    |    |    |    |    |    (cc 0 1)
396 ;; TRACE t2660: |    |    |    |    |    |    |    => 1
397 ;; TRACE t2658: |    |    |    |    |    |    => 1
398 ;; TRACE t2661: |    |    |    |    |    |    (cc -4 2)
399 ;; TRACE t2661: |    |    |    |    |    |    => 0
400 ;; TRACE t2657: |    |    |    |    |    => 1
401 ;; TRACE t2662: |    |    |    |    |    (cc -9 3)
402 ;; TRACE t2662: |    |    |    |    |    => 0
403 ;; TRACE t2656: |    |    |    |    => 1
404 ;; TRACE t2612: |    |    |    => 4
405 ;; TRACE t2663: |    |    |    (cc -14 4)
406 ;; TRACE t2663: |    |    |    => 0
407 ;; TRACE t2611: |    |    => 4
408 ;; TRACE t2664: |    |    (cc -39 5)
409 ;; TRACE t2664: |    |    => 0
410 ;; TRACE t2610: |    => 4
411 ;; TRACE t2609: => 4
412 ;; 4  
413 ;; )
414
415
416 ;; TODO: orders of growth in space and number of steps.
417
418 ;; exercise 1.15: sin (x) calculation
419 ;;    a.  How many times is the procedure p applied when (sine 12.15)
420 ;;        is evaluated?
421 ;;    b.  What is the order of growth in space and number of steps (as
422 ;;        a function of a) used by the process generated by the sine
423 ;;        procedure when (sine a) is evaluated?
424 (defn p [x] (- (* 3 x) (* 4 (cube x))))
425
426 (defn sine [angle]
427   (if (not (> (myabs angle) 0.1))
428     angle
429     (p (sine (/ angle 3.0)))))
430
431 ;; solution to (a) => 5
432 ;; (comment
433 ;; user> (dotrace [p] (sine 12.15))
434 ;; TRACE t2490: (p 0.049999999999999996)
435 ;; TRACE t2490: => 0.1495
436 ;; TRACE t2491: (p 0.1495)
437 ;; TRACE t2491: => 0.4351345505
438 ;; TRACE t2492: (p 0.4351345505)
439 ;; TRACE t2492: => 0.9758465331678772
440 ;; TRACE t2493: (p 0.9758465331678772)
441 ;; TRACE t2493: => -0.7895631144708228
442 ;; TRACE t2494: (p -0.7895631144708228)
443 ;; TRACE t2494: => -0.39980345741334
444 ;; -0.39980345741334
445 ;; )
446
447 ;; solution to b
448 ;; both space and number of steps grows as log3(a) -> log a to the base 3.
449 ;;
450 ;; proof:
451 ;;   a * (1/3)^n <= 0.1
452 ;;   => take log to the base 3 on both the sides.
453
454 ;; Note: Finding the order of space in a recursive process is sort of, equiv
455 ;;       to finding the number of deferred operations. Which is in-turn the
456 ;;       same as the depth of the evaluation tree.
457
458 ;; 1.2.4: exponentiation
459 ;; computing b^n
460
461 ;; iterative
462 (defn expt-iter [base counter product]
463   (if (= counter 0)
464     product
465     (expt-iter base
466                (dec counter)
467                (* product base))))
468
469 (defn myexpt [b n]
470   (expt-iter b n 1))
471
472 (defn myexpt [b n]
473   (if (= n 0)
474     1
475     (* b (myexpt b (dec n)))))
476
477 ;; fast version
478 (defn fast-expt [b n]
479   (cond (= n 0) 1
480         (even? n) (square (fast-expt b (/ n 2)))
481         :else (* b (fast-expt b (dec n)))))
482
483 ;; exercise 1.16:
484 (defn myexpt [b n]
485   (expt-iter b n 1))
486
487 (defn expt-iter [b n a]
488   (cond (= n 0) a
489         (even? n) (expt-iter (square b) (/ n 2) a)
490         :else (expt-iter b (- n 1) (* a b))))
491
492 ;; exercise 1.17:
493 (defn mult [a b]
494   (if (= b 0)
495     0
496     (+ a (mult a (- b 1)))))
497
498 ;; double
499 ;; product = 2 * (a * (b/2)) for even b
500 ;;         = a    + (a * (b - 1)) for odd b
501 (defn fast-mult [a b]
502   (cond (= b 0) 0
503         (= b 1) a
504         (even? b) (twice (fast-mult a (half b)))
505         :else (+ a (fast-mult a (- b 1)))))
506
507 ;; exercise 1.18: iterative multiply thru addition
508 ;; the idea is to keep a state variable.
509 (defn fast-mult-iter [a b k]
510   (cond (= b 0) k
511         (even? b) (fast-mult-iter (twice a) (half b) k)
512         :else (fast-mult-iter a (- b 1) (+ k a))))
513
514 (defn fast-mult-new [a b]
515   (fast-mult-iter a b 0))
516
517 ;; (comment
518 ;; user> (dotrace [fast-mult-new fast-mult-iter] (fast-mult-new 2 3))
519 ;; TRACE t2915: (fast-mult-new 2 3)
520 ;; TRACE t2916: |    (fast-mult-iter 2 3 0)
521 ;; TRACE t2917: |    |    (fast-mult-iter 2 2 2)
522 ;; TRACE t2918: |    |    |    (fast-mult-iter 4 1 2)
523 ;; TRACE t2919: |    |    |    |    (fast-mult-iter 4 0 6)
524 ;; TRACE t2919: |    |    |    |    => 6
525 ;; TRACE t2918: |    |    |    => 6
526 ;; TRACE t2917: |    |    => 6
527 ;; TRACE t2916: |    => 6
528 ;; TRACE t2915: => 6
529 ;; 6
530 ;; )
531
532 ;; exercise 1.19: fast fibonacci
533 ;; see the pdf of the notebook scan for the derivation of p' and q'
534 (defn ffib-iter [a b p q count]
535   (cond (= count 0) b
536         (even? count)
537         (ffib-iter a
538                    b
539                    (+ (* p p) (* q q))
540                    (+ (* 2 p q) (* q q))
541                    (/ count 2))
542         :else (ffib-iter (+ (* b q) (* a q) (* a p))
543                          (+ (* b p) (* a q))
544                          p
545                          q
546                          (- count 1))))
547
548 (defn ffib [n]
549   (ffib-iter 1 0 0 1 n))
550
551 ;;;  Section 1.2.5: GCD
552 (defn mygcd [a b]
553   (if (= b 0)
554     a
555     (mygcd b (rem a b))))
556
557 ;;; exercise 1.20.
558 ;;
559 ;;  normal order - 18, applicative order - 4.
560 ;;
561 ;;   too lazy to scan things from the notebook. May be I should instead
562 ;;   use a wiki.
563
564 ;;; section 1.2.6 Primality testing.
565 (defn prime? [n]
566   (= (smallest-divisor n) n))
567
568 (defn smallest-divisor [n]
569   (find-divisor n 2))
570
571 (defn find-divisor [n test-divisor]
572   (cond (> (square test-divisor)  n) n
573         (divides? test-divisor n) test-divisor
574         :else (find-divisor n (inc test-divisor))))
575
576 (defn divides? [a b]
577   (= (rem b a) 0))
578
579 ;; fermat's little theorem
580 (defn expmod [base exp m]
581   (cond (= exp 0) 1
582         (even? exp) (rem (square (expmod base (/ exp 2) m))
583                          m)
584         :else (rem (* base (expmod base (dec exp) m))
585                    m)))
586
587 (defn fermat-test [n]
588   (try-it (+ 1 (rand-int (- n 1))) n))
589
590 (defn try-it [a n]
591   (= a (expmod a n n)))
592
593 (defn fast-prime? [n times]
594   (cond (= times 0) true
595         (fermat-test n) (fast-prime? n (dec times))
596         :else false))
597
598 ;; exercise 1.21
599 (comment
600 user> (smallest-divisor 199)
601 199
602 user> (smallest-divisor 1999)
603 1999
604 user> (smallest-divisor 19999)
605 7
606 )
607
608 ;; exercise 1.22
609 (defn timed-prime-test [n]
610   (prn)
611   (print n)
612   (start-prime-test n (System/nanoTime)))
613
614 (defn start-prime-test [n start-time]
615   (if (prime? n)
616     (report-prime (- (System/nanoTime) start-time))))
617
618 (defn report-prime [elapsed-time]
619   (print " *** ")
620   (print elapsed-time))
621
622 (defn search-for-primes [a b]
623   (cond (>= a b) nil
624         (even? a) (search-for-primes (+ 1 a) b)
625         (timed-prime-test a) (search-for-primes (+ 2 a) b)
626         :else (search-for-primes (+ 2 a) b)))
627
628 ;;; three smallest primes greater than 1000
629 ;;; 1009, 1013, 1019
630 (take 3 (filter #(prime? %) (iterate inc 1000)))
631 ;=> (1009 1013 1019)
632
633 ;=> 0.9642028750000001
634
635 ;;; > 10,000: 10007, 10009, 10037
636 (take 3 (filter #(prime? %) (iterate inc 10000)))
637 ;=> (10007 10009 10037)
638
639 ;=> 1.5897884999999998
640
641 ;;; > 100,000: 100003, 100019, 100043
642 (take 3 (filter #(prime? %) (iterate inc 100000)))
643 ;=> (100003 100019 100043)
644
645 ;=> 1.8525091250000003
646
647 ;;; > 1,000,000: 1000003, 1000033, 1000037
648 (take 3 (filter #(prime? %) (iterate inc 1000000)))
649 ;=> (1000003 1000033 1000037)
650
651 ;=> 1.908832125
652
653 ;; time taken seem to increase as the range increases.
654 ;; but they are totally random on the jvm, so I can't find
655 ;; the exact relation.
656
657 (comment
658 user> (microbench 10 (take 3 (filter #(prime? %) (iterate inc 1000))))
659 Warming up!
660 Benchmarking...
661 (1009 1013 1019)
662 (1009 1013 1019)
663 (1009 1013 1019)
664 (1009 1013 1019)
665 (1009 1013 1019)
666 (1009 1013 1019)
667 (1009 1013 1019)
668 (1009 1013 1019)
669 (1009 1013 1019)
670 (1009 1013 1019)
671 Total runtime:  0.28404500000000005
672 Highest time :  0.083949
673 Lowest time  :  0.019416
674 Average      :  0.022585000000000008
675 (0.083949 0.019416 0.023257 0.020394 0.024165 0.024514 0.024374 0.020813 0.021721 0.021442)
676 user> (microbench 10 (take 3 (filter #(prime? %) (iterate inc 10000))))
677 Warming up!
678 Benchmarking...
679 (10007 10009 10037)
680 (10007 10009 10037)
681 (10007 10009 10037)
682 (10007 10009 10037)
683 (10007 10009 10037)
684 (10007 10009 10037)
685 (10007 10009 10037)
686 (10007 10009 10037)
687 (10007 10009 10037)
688 (10007 10009 10037)
689 Total runtime:  0.26462800000000003
690 Highest time :  0.067118
691 Lowest time  :  0.020533
692 Average      :  0.022122125000000006
693 (0.067118 0.022698 0.024095 0.023537 0.020533 0.020882 0.020603 0.021372 0.020603 0.023187)
694 user> (microbench 10 (take 3 (filter #(prime? %) (iterate inc 100000))))
695 Warming up!
696 Benchmarking...
697 (100003 100019 100043)
698 (100003 100019 100043)
699 (100003 100019 100043)
700 (100003 100019 100043)
701 (100003 100019 100043)
702 (100003 100019 100043)
703 (100003 100019 100043)
704 (100003 100019 100043)
705 (100003 100019 100043)
706 (100003 100019 100043)
707 Total runtime:  0.265118
708 Highest time :  0.073263
709 Lowest time  :  0.020254
710 Average      :  0.021450125000000004
711 (0.073263 0.023048 0.023467 0.021022 0.020394 0.020254 0.021302 0.020812 0.020743 0.020813)  
712 )
713
714 ;;; can't make out any sqrt(10) relation between the numbers. may be because
715 ;;; jvm compilation is doing some behind the scene tricks.
716
717 ;;; exercise 1.23
718 (defn next-divisor [n]
719   (if (= n 2)
720     3
721     (+ n 2)))
722
723
724 (defn find-divisor [n test-divisor]
725   (cond (> (square test-divisor)  n) n
726         (divides? test-divisor n) test-divisor
727         :else (find-divisor n (next-divisor test-divisor))))
728
729 (comment
730   I can't see any noticable difference in the speed.
731   )
732
733 ;;; exercise 1.24
734 (comment
735   (microbench 10 (take 3 (filter #(fast-prime? %) (iterate inc 1000))))
736   ...
737   "I did not observe any difference".
738   )
739
740 ;; exercise 1.25
741 (defn expmod [base exp m]
742   (rem (fast-expt base exp) m))
743
744 (comment
745   In the case of the original expmod implementation, square and remainder
746   calls are interspersed, so square always deals with a small number, whereas
747   with the above way, we do a series of squaring and then in the end take
748   remainder. Squaring of big numbers are very inefficient as the CPU has to
749   do multi-byte arithmetic which consumes many cycles.
750
751   So the new version is several times slower than the original.
752 )
753
754 ;;; exercise 1.26
755 (comment
756   "Instead of calling (square x), Louis now makes does (* x x). In the former,
757    case, x is evaluated only once, where as in the second, x gets evaluated
758    2x, 4x, 8x, 16x and so on (for any x which is recursive). So, if the original
759    computation is considered T(log_n), then the new process T(n). This can also
760    be illustrated with the call tree."
761 )
762
763 ;; exercise 1.27
764 (comment
765   "Some notes on Carmichael numbers: Carmichael numbers are those that fail
766    Fermat little test. That is, for any n in the Carmichael set,
767    (prime? n)      => false
768    (fermat-test n) => true."
769   )
770 (defn brute-force-fermat-test [n]
771   (try-all 2 n))
772
773 (defn try-all [a n]
774   (cond (= a n) true
775         (try-it a n) (try-all (inc a) n)
776         :else false))
777 (comment
778   "all the given numbers pass the above test, i.e. for every a < n,
779    a^n mod n === a mod n"
780   user> (brute-force-fermat-test 561)
781   true
782   user> (brute-force-fermat-test 1105)
783   true
784   user> (brute-force-fermat-test 1729)
785   true
786   user> (brute-force-fermat-test 2465)
787   true
788   user> (brute-force-fermat-test 2821)
789   true
790   user> (brute-force-fermat-test 6601)
791   true
792   )
793
794 ;;; exercise 1.28
795 (defn expmod2 [base exp m]
796   (cond (= exp 0) 1
797         (even? exp) (square-test (expmod2 base (/ exp 2) m) m)
798         :else (rem (* base (expmod2 base (dec exp) m))
799                    m)))
800
801 (defn square-test [x m]
802   (if (and (not (or (= x 1) (= x (- m 1))))
803            (= (rem (square x) m) 1))
804     0
805     (rem (square x) m)))
806
807 (defn miller-rabin-test [n]
808   (try-it (+ 2 (rand-int (- n 2)))
809           n))
810
811 (defn try-it [a n]
812   (= (expmod2 a (- n 1) n) 1))
813
814 (comment
815   "If the random number generated (a) is 1, then this returns false
816    positives. So generate random numbers between 2 and n-1. (is this
817    assumption correct?) "
818   
819   )