]> git.rkrishnan.org Git - sicp.git/blob - src/sicp/ch2_2.clj
examples till ex 2.33.
[sicp.git] / src / sicp / ch2_2.clj
1 (ns sicp.ch2-2
2   (:refer-clojure :exclude (map))
3   (:use [sicp [ch1-2 :only (fib)]]
4         [clojure.test]))
5
6 (cons 1
7       (cons 2
8             (cons 3
9                   (cons 4 nil))))
10 ;;=> (1 2 3 4)
11 (list 1 2 3 4)
12
13 (def one-thru-four (list 1 2 3 4))
14 ;;=> #'user/one-thru-four
15 (first one-thru-four)
16 ;;=> 1
17 (rest one-thru-four)
18 ;;=> (2 3 4)
19 (cons 10 one-thru-four)
20 ;;=> (10 1 2 3 4)
21 (cons 5 one-thru-four)
22 ;;=> (5 1 2 3 4)
23
24 ;; get nth element of a list
25 (defn list-ref [items n]
26   (if (= n 0)
27     (first items)
28     (list-ref (rest items) (- n 1))))
29
30 (list-ref one-thru-four 3)
31 ;;=> 4
32 (list-ref one-thru-four 5)
33 ;;=> nil
34 (list-ref one-thru-four 1)
35 ;;=> 2
36 (list-ref one-thru-four 0)
37 ;;=> 1
38
39 (defn length [items]
40   (if (empty? items)
41     0
42     (+ 1 (length (rest items)))))
43
44 (length one-thru-four)
45 ;;=> 4
46
47 (defn- length-i [items n]
48   (if (empty? items)
49     n
50     (length-i (rest items) (+ 1 n))))
51
52 (defn length-iter [items]
53   (length-i items 0))
54
55 (length-iter one-thru-four)
56 ;;=> 4
57
58 (defn append [list1 list2]
59   (if (empty? list1)
60     list2
61     (cons (first list1)
62           (append (rest list1) list2))))
63
64 (append one-thru-four one-thru-four)
65 ;;=> (1 2 3 4 1 2 3 4)
66
67 ;; mapping over lists
68 (defn scale-list [items factor]
69   (if (empty? items)
70     nil
71     (cons (* factor (first items))
72           (scale-list (rest items) factor))))
73
74 (defn map [proc items]
75   (if (empty? items)
76     nil
77     (cons (proc (first items))
78           (map proc (rest items)))))
79
80 (defn scale-list-with-map [items factor]
81   (map (fn [item] (* item factor)) items))
82
83 ;; 2.2.2
84 (def x (cons (list 1 2) (list 3 4)))
85
86 (length x)
87 ;;=> 3
88
89 ;; count-leaves
90 (defn count-leaves [coll]
91   (cond (nil? coll)       0
92         (not (seq? coll)) 1
93         :else (+ (count-leaves (first coll))
94                  (count-leaves (next coll)))))
95
96 ;; mapping over trees
97 (defn scale-tree [tree factor]
98   (cond (nil? tree) nil
99         (not (seq? tree)) (* tree factor)
100         :else (cons (scale-tree (first tree) factor)
101                     (scale-tree (next tree) factor))))
102
103 ;; using map
104 (defn scale-tree-with-map [tree factor]
105   (map (fn [sub-tree]
106          (if (seq? sub-tree)
107            (scale-tree-with-map sub-tree factor)
108            (* sub-tree factor)))
109        tree))
110
111 ;;; 2.2.3
112 (defn sum-odd-squares [tree]
113   (cond (nil? tree) 0
114         (not (seq? tree)) (if (odd? tree)
115                             ((fn [x] (* x x)) tree)
116                             0)
117         :else (+ (sum-odd-squares (first tree))
118                  (sum-odd-squares (next tree)))))
119
120 (defn even-fibs [n]
121   (letfn [(next-fib [k]
122                     (if (> k n)
123                       nil
124                       (let [f (fib k)]
125                         (if (even? f)
126                           (cons f (next-fib (+ k 1)))
127                           (next-fib (+ k 1))))))]
128     (next-fib 0)))
129
130 (map #(* % %) (list 1 2 3 4 5))
131
132 (defn myfilter-1 [pred? xs]
133   (cond (nil? xs) nil
134         (not (seq? xs)) (if (pred? xs)
135                           (list xs)
136                           ())
137         :else (concat (myfilter-1 pred? (first xs))
138                       (myfilter-1 pred? (next xs)))))
139
140 (defn myfilter-2 [pred? xs]
141   (cond (nil? xs) nil
142         (pred? (first xs)) (cons (first xs)
143                                  (myfilter-2 pred? (next xs)))
144         :else (myfilter-1 pred? (next xs))))
145
146 ;; accumulate
147 (defn accumulate [op init xs]
148   (if (nil? xs)
149     init
150     (op (first xs)
151         (accumulate op init (next xs)))))
152
153 (defn enumerate-interval
154   ([high]
155      (enumerate-interval 0 high))
156   ([low high]
157      (if (> low high)
158        nil
159        (cons low (enumerate-interval (+ low 1) high)))))
160
161 ;; same as flatten/fringe
162 (defn enumerate-tree [tree]
163   (cond (nil? tree) nil
164         (not (seq? tree)) (list tree)
165         :else (concat (enumerate-tree (first tree))
166                       (enumerate-tree (next tree)))))
167
168 (defn square [x] (* x x))
169
170 ;; define sum of odd squares in terms of myfilter-2, enumerate, accumulate
171 (defn sum-of-odd-squares [tree]
172   (->> tree
173        (enumerate-tree)
174        (filter odd?)
175        (map square)
176        (accumulate + 0)))
177
178 (deftest test-sum-of-odd-squares
179   (is [= (sum-of-odd-squares '((1) (2) (3 4) ((5) (((6) (7)) (8)))))
180          (reduce + (map #(* % %) (filter odd? (range 1 9))))]))
181
182 (defn even-fibs-new [n]
183   (->> n
184        (enumerate-interval ,,,)
185        (map fib ,,,)
186        (filter even? ,,,)
187        (accumulate cons nil ,,,)))
188
189 (defn list-fib-squares [n]
190   (->> n
191        (enumerate-interval ,,,)
192        (map fib ,,,)
193        (map square ,,,)
194        (accumulate cons nil ,,,)))
195
196 (defn product-of-squares-of-odd-elements [sequence]
197   (accumulate *
198               1
199               (map square
200                    (filter odd? sequence))))
201
202 ;; note how beautiful and clear the clojure ->> macro is!
203 (defn product-of-squares-of-odd-elements [sequence]
204   (->> sequence
205        (filter odd? ,,,)
206        (map square ,,,)
207        (accumulate * 1 ,,,)))
208