]> git.rkrishnan.org Git - sicp.git/blob - src/sicp/ch2_2.clj
added parts of section 2.2.3
[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
5 (cons 1
6       (cons 2
7             (cons 3
8                   (cons 4 nil))))
9 ;;=> (1 2 3 4)
10 (list 1 2 3 4)
11
12 (def one-thru-four (list 1 2 3 4))
13 ;;=> #'user/one-thru-four
14 (first one-thru-four)
15 ;;=> 1
16 (rest one-thru-four)
17 ;;=> (2 3 4)
18 (cons 10 one-thru-four)
19 ;;=> (10 1 2 3 4)
20 (cons 5 one-thru-four)
21 ;;=> (5 1 2 3 4)
22
23 ;; get nth element of a list
24 (defn list-ref [items n]
25   (if (= n 0)
26     (first items)
27     (list-ref (rest items) (- n 1))))
28
29 (list-ref one-thru-four 3)
30 ;;=> 4
31 (list-ref one-thru-four 5)
32 ;;=> nil
33 (list-ref one-thru-four 1)
34 ;;=> 2
35 (list-ref one-thru-four 0)
36 ;;=> 1
37
38 (defn length [items]
39   (if (empty? items)
40     0
41     (+ 1 (length (rest items)))))
42
43 (length one-thru-four)
44 ;;=> 4
45
46 (defn- length-i [items n]
47   (if (empty? items)
48     n
49     (length-i (rest items) (+ 1 n))))
50
51 (defn length-iter [items]
52   (length-i items 0))
53
54 (length-iter one-thru-four)
55 ;;=> 4
56
57 (defn append [list1 list2]
58   (if (empty? list1)
59     list2
60     (cons (first list1)
61           (append (rest list1) list2))))
62
63 (append one-thru-four one-thru-four)
64 ;;=> (1 2 3 4 1 2 3 4)
65
66 ;; mapping over lists
67 (defn scale-list [items factor]
68   (if (empty? items)
69     nil
70     (cons (* factor (first items))
71           (scale-list (rest items) factor))))
72
73 (defn map [proc items]
74   (if (empty? items)
75     nil
76     (cons (proc (first items))
77           (map proc (rest items)))))
78
79 (defn scale-list-with-map [items factor]
80   (map (fn [item] (* item factor)) items))
81
82 ;; 2.2.2
83 (def x (cons (list 1 2) (list 3 4)))
84
85 (length x)
86 ;;=> 3
87
88 ;; count-leaves
89 (defn count-leaves [coll]
90   (cond (nil? coll)       0
91         (not (seq? coll)) 1
92         :else (+ (count-leaves (first coll))
93                  (count-leaves (next coll)))))
94
95 ;; mapping over trees
96 (defn scale-tree [tree factor]
97   (cond (nil? tree) nil
98         (not (seq? tree)) (* tree factor)
99         :else (cons (scale-tree (first tree) factor)
100                     (scale-tree (next tree) factor))))
101
102 ;; using map
103 (defn scale-tree-with-map [tree factor]
104   (map (fn [sub-tree]
105          (if (seq? sub-tree)
106            (scale-tree-with-map sub-tree factor)
107            (* sub-tree factor)))
108        tree))
109
110 ;;; 2.2.3
111 (defn sum-odd-squares [tree]
112   (cond (nil? tree) 0
113         (not (seq? tree)) (if (odd? tree)
114                             ((fn [x] (* x x)) tree)
115                             0)
116         :else (+ (sum-odd-squares (first tree))
117                  (sum-odd-squares (next tree)))))
118
119 (defn even-fibs [n]
120   (letfn [(next-fib [k]
121                     (if (> k n)
122                       nil
123                       (let [f (fib k)]
124                         (if (even? f)
125                           (cons f (next-fib (+ k 1)))
126                           (next-fib (+ k 1))))))]
127     (next-fib 0)))
128
129 (map #(* % %) (list 1 2 3 4 5))
130
131 (defn myfilter-1 [pred? xs]
132   (cond (nil? xs) nil
133         (not (seq? xs)) (if (pred? xs)
134                           (list xs)
135                           ())
136         :else (concat (myfilter-1 pred? (first xs))
137                       (myfilter-1 pred? (next xs)))))
138
139 (defn myfilter-2 [pred? xs]
140   (cond (nil? xs) nil
141         (pred? (first xs)) (cons (first xs)
142                                  (myfilter-2 pred? (next xs)))
143         :else (myfilter-1 pred? (next xs))))
144
145 ;; accumulate
146 (defn accumulate [op init xs]
147   (if (nil? xs)
148     init
149     (op (first xs)
150         (accumulate op init (next xs)))))
151
152 (defn enumerate-interval
153   ([high]
154      (enumerate-interval 0 high))
155   ([low high]
156      (if (> low high)
157        nil
158        (cons low (enumerate-interval (+ low 1) high)))))