-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexercises.clj
353 lines (255 loc) · 10.3 KB
/
exercises.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
(ns clojureexercisescis554.core)
;; (ns user (:use clojure.test))
(defn foo
"I don't do a whole lot."
[x]
(println x "Hello, World!"))
;test basic function
(defn double-num [n]
(* n 2))
(double-num 5)
;;;;;;FIRST GROUP;;;;;
;(atomic? v)
;Returns true if v is not any kind of a collection (check with coll?), and false otherwise.
(defn atomic? [v]
(if (not (coll? v ))
true
false))
(atomic? 5)
(atomic? nil)
(atomic? '[5 3])
;(member? x lst)
;Returns a true value if x is in lst.
(defn member? [x lst]
(if (empty? lst)
false
(if (= x (first lst))
true
(member? x (rest lst)))))
(member? 5 [1 2 5 6])
(member? 5 [1 2 6])
;(my-count lst)
;Returns the number of "top level" elements in lst. For example, (a (b c (d e)) f) has 3 top level elements
;(b c (d e)) is a single top-level element. (a b () d) has 4 top-level elements.
(defn my-count [lst]
(if (empty? lst)
0
(+ 1 (my-count (rest lst)))))
(my-count '(a (b c (d e)) f))
;(append lst1 lst2)
;Combine lst1 and lst2 into a single list. For example, if lst1 is (:a :b :c) and lst2 is (1 (2 3))
;the result should be (:a :b :c 1 (2 3)).
(defn append [lst1 lst2]
(if (empty? lst1) lst2
(if-not (empty? lst1)
(cons
(first lst1)
(append (rest lst1) lst2)) )))
;; (cons lst1 lst2))
(append '(:a :b :c) '(1 (2 3)))
;(zip lst1 lst2)
;Combine corresponding elements of lst1 and lst2 into a list of two-element lists
;stop when you run out of elements in either list. For example, if lst1 is (:a :b :c) and lst2 is (1 (2 3) 4 5)
;the result should be ((:a 1) (:b (2 3)) (:c 4)).
(defn zip [lst1 lst2]
(if
(or (empty? lst1) (empty? lst2) )
()
(cons
(concat (list (first lst1)) (list (first lst2) ))
(zip (rest lst1) (rest lst2)))
)
)
(zip '(:a :b :c) '(1 (2 3) 4 5))
;(lookup key list-of-pairs)
;Given an S-expression key and a list of (key value) pairs, return the value that corresponds to the key
;or nil if there is no such pair. You can assume that there is only one such pair.
(defn lookup [key list-of-pairs]
(cond
(empty? list-of-pairs) nil
(= key (first (first list-of-pairs))) (second (first list-of-pairs))
:else (lookup key (rest list-of-pairs))))
(lookup 5 '((5, 5) (5, 3)))
;(my-merge lst1 lst2)
;Given two lists of integers, where each list is in ascending order, merge them into a single list that is also in ascending order
;For example, if lst1 is (3 7 12 19 19 25 30) and lst2 is (4 7 10 12 20), the result should be (3 4 7 7 10 12 12 19 19 20 25 30).
(defn my-merge [lst1 lst2]
(cond
(empty? lst1) lst2
(empty? lst2) lst1
(< (first lst1) (first lst2)) (cons (first lst1) (my-merge (rest lst1) lst2))
:else (cons (first lst2) (my-merge lst1 (rest lst2)))))
(my-merge '(3 7 12 19 19 25 30) '(4 7 10 12 20))
;(count-all lst)
;Returns the total number of atomic elements in lst, at all levels.
;For example, (a (b c () (25) nil) ()) has 5 atomic elements: a, b, c, 25, and nil.
;; (defn count-all [lst]
;; (if (empty? (first lst) ) (count-all (rest lst))
;; (if (empty? (rest lst) ) 0
;; (+ 1 (count-all (list ((rest (first lst)) ) ) ) ) ) ) )
(defn count-all [lst]
(if (empty? lst)
0
(if (atomic? (first lst)) (+ 1 (count-all (rest lst)))
(+ (count-all (first lst)) (count-all (rest lst))) )))
(count-all '( (a b) (b c () (25) nil) ()) )
;(my-drop n lst)
;Returns the lst with the first n elements removed. For example, (my-drop 3 '(a b c d e)) should return (d e))
;If n is equal to or greater than the length of the list lst, return the empty list, ().
(defn my-drop [n lst]
(if (>= n (count lst ))
(rest lst)
(rest (my-drop (+ 1 (count lst) ) (rest lst) ) )))
(my-drop 3 '(a b c d e) )
;(my-take n lst)
;Returns a list of the first n elements of lst. If lst has fewer than n elements, the result is just lst.
;Strong hint: Use two parameters lists, the second one using an "accumulator" parameter to collect the elements taken from lst.
;You are likely to find reverse to be useful.
(defn my-take [n lst]
(if (>= (+ n 1) (count lst ) ) ()
(cons (first lst) (my-take (+ 1 (count (list (first lst)) ) ) (rest lst)))))
(my-take 3 '(1 2 3 4 5 6))
;(my-reverse lst)
;Reverses the elements of list lst. For example, the list (1 2 (3 4)) becomes the sequence ((3 4) 2 1).
(defn my-reverse [lst]
(if (empty? lst) ()
(cons (last lst) (my-reverse (butlast lst)))))
(my-reverse '(1 2 3 4 5 6))
;(remove-duplicates lst)
;Removes duplicate top-level elements of lst. For example, given (1 2 3 1 4 1 2),
;remove-duplicates returns a sequence containing the elements (1 2 3 4), in some order.
(defn remove-duplicates [lst]
(if-not (empty? lst)
(cons
(first lst)
(filter
(fn [item] (not= item (first lst)))
(remove-duplicates (next lst))))))
(remove-duplicates '(2 4 5 6 5))
;(my-flatten list-of-lists)
;Removes one level of parentheses (or brackets) removed, returning a "flatter" list of values.
;For example, if lst is ( ( (1 1) (2 3) ) ( (5 7) ) ), the result should be ((1 1) (2 3) (5 7)).
;; (defn my-flatten [lst]
;; (if (empty? lst) ()
;; (concat (if (seq? (first lst)) (my-flatten (first lst))
;; (list (first lst)))
;; (my-flatten (rest lst)))))
(defn my-flatten [lst]
(if (empty? lst) ()
(concat (first lst) (my-flatten (rest lst)))))
(my-flatten '( ( (1 1) (2 3) ) ( (5 7) ) ))
;;;;;;SECOND GROUP;;;;;
;(buzz list-of-ints)
;Return the same list of integers as given as an argument, except that every number divisible by 7, or containing the digit 7,
;has been replaced by :buzz. Hint: (seq string) returns a list of characters, and map is useful.
(defn buzz [list-of-ints]
(map #(cond (or
(= 0 (mod % 7))
(.contains (seq "%") 7 ) ) "Buzz" ;;seq sring doesn't work?
:else %) list-of-ints))
(buzz '(7 77 5))
;(divisors-of n)
;For positive integer n, returns the divisors of n, other than 1 and n itself. For example, 12 has divisors (2, 3, 4, 6).
;Hint: Use mod and filter.
(defn divisors-of [n]
(filter (fn [x] (= 0 (mod n x))) (range 2 n)))
(divisors-of 6)
;(longest list-of-strings)
;Returns the longest string in the list-of-strings; if there is more than one longest string,
;return the earlier one. Assume that list-of-strings is not empty. Hint: reduce.
(defn longest [list-of-strings]
(reduce (fn [fst scnd]
(if (> (count fst) (count scnd)) fst
scnd))
"" list-of-strings))
(longest '("abcde", "abc", "abcdqjf"))
;;;;;;THIRD GROUP;;;;;
;red0
;(my-map f lst)
;Apply the function f to each element of lst, returning a list of the results.
(defn my-map [f lst]
(cond (empty? lst) ()
:else (cons (f (first lst)) (map f (rest lst)))))
(my-map (+ 2) '(2 4 6))
;(my-filter pred lst)
;Apply the test pred to each element of lst, returning a list of the ones that pass the test.
(defn my-filter [pred lst]
(cond (empty? lst) ()
(my-filter (first lst)) (cons (pred (first list)) (map pred (rest list)))
:else (filter my-filter (rest list))))
(my-filter (> 3) '(2 4 6))
;(my-reduce f value? lst)
;Applies the two-parameter function f to the value? and the first element of the sequence (if value? is present),
;else to the first two elements of the sequence; applies the function to the result and the next element in the list, recursively.
;Hint: Since this function takes two or three arguments, you have to use the proper syntax for this. See Defining and calling functions in my Concise Guide to Clojure.
(defn init [s]
[[] (ref {:s s :index 0})])
(defn my-reduce [f value? lst]
(cond (value? nil) (my-reduce f (first lst) (second lst) )
([f init lst]
(cons init (lazy-seq if (empty? lst) nil)
:else (my-reduce (f (apply f (list init (first lst))) (rest lst) ) ) ) ) ))
;(my-flat-map f lst)
;f must be a function that returns lists. my-flat-map applies the function f to each element of lst, flattens the resultant list by removing one level of parentheses, and returns the result.
(defn my-flat-map [f lst]
(cond (empty? lst) ()
(number? (first lst))
(cons (my-map (f (first lst)) (my-flat-map (rest lst)))
:else (append (my-flat-map (first lst)) (my-flat-map (rest lst))))))
(my-flat-map (+ 1 (2 (3 4) (6 (5 7)))) '(3 4 (5 6) (8 (7 9))))
;;TESTS;
(deftest test-atomic?
(is (= true (atomic? 5))))
(deftest test-atomic?
(is (= true (atomic? nil))))
(deftest test-atomic?
(is (= false (atomic? '[5 3]))))
(deftest test-member?
(is (= true (member? 5 '(1 2 3 5)))))
(deftest test-member?
(is (= false (member? 6 '(1 2 3 5)))))
(deftest test-my-count
(is (= 3 (my-count '(a (b c (d e)) f) ) )))
(deftest test-my-count
(is (= 4 (my-count '(a (b c (d e)) f g) ) )))
(deftest test-append
(is (= (:a :b :c 1 (2 3)) (append '(:a :b :c) '(1 (2 3))) ) ))
(deftest test-append
(is (= (:a :b :c 1 (2 3)) (append '(a (b c (d e)) f g) ) ) ))
(deftest test-zip
(is (= ((:a 1) (:b (2 3)) (:c 4)) (zip '(:a :b :c) '(1 (2 3) 4 5)))))
(deftest test-lookup
(is (= 5 (lookup 5 '((5, 5) (5, 3))))))
(deftest test-my-merge
(is (= (3 4 7 7 10 12 12 19 19 20 25 30) (my-merge '(3 7 12 19 19 25 30) '(4 7 10 12 20)))))
(deftest test-count-all
(is (= 5 (count-all '(a (b c () (25) nil) ()) ) )))
(deftest test-my-drop
(is (= (d e) (my-drop 3 '(a b c d e)))))
(deftest test-my-take
(is (= (1 2 3) (my-take 3 '(1 2 3 4 5 6)))))
(deftest test-my-reverse
(is (= (6 5 4 3 2 1) (my-reverse '(1 2 3 4 5 6)))))
(deftest test-remove-duplicates
(is (= (2 4 5 6) (remove-duplicates '(2 4 5 6 5)))))
(deftest test-my-flatten
(is (= ((1 1) (2 3) (5 7)) (my-flatten '( ( (1 1) (2 3) ) ( (5 7) ) )))))
(deftest test-buzz
(is (= ("Buzz" "Buzz" 5) (buzz '(7 77 5)))))
(deftest test-divisors-of
(is (= (2 3) (divisors-of 6))))
(deftest test-divisors-of
(is (= (2 5) (divisors-of 10))))
(deftest test-longest
(is (= "abcdqjf" (longest '("abcde", "abc", "abcdqjf")))))
(deftest test-longest
(is (= "abcdqjf" (longest '("", "", "abcdqjf")))))
(deftest test-my-map
(is (= (4 6 8) (my-map (+ 2) '(2 4 6)))))
(deftest test-my-filter
(is (= (6 8) (my-filter ((> 3) '(2 4 6))))))
(deftest test-my-reduce
(is (= (25) '(my-reduce (+ 2 lst) (5) '(3 4 5)))))
(deftest test-my-flat-map
(is (= (3 4 (5 6) (8 (7 9)))) (my-flat-map (+ 1 (2 (3 4) (6 (5 7)))))))
(run-tests)