-
Notifications
You must be signed in to change notification settings - Fork 1
/
ch10p09_sorted_matrix_search.clj
87 lines (79 loc) · 2.03 KB
/
ch10p09_sorted_matrix_search.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
#!/usr/bin/env bb
(require '[clojure.test :as t])
(defn binary-search-comparator [vs comparator]
(when-not (empty? vs)
(let [midpoint (quot (count vs) 2)
mid-v (nth vs midpoint)
cmp (comparator mid-v)]
(cond
(neg? cmp) (binary-search-comparator (subvec vs 0 midpoint) comparator)
(zero? cmp) midpoint
(pos? cmp) (+ (inc midpoint)
(binary-search-comparator (subvec vs (inc midpoint)) comparator))))))
(defn binary-search
"Find index of v in vs where vs is ascending"
[vs v]
(binary-search-comparator vs #(compare v %)))
(defn binary-search-matrix
"Find the index of the row within range of vss, where vs in vss are ascending"
[vss v]
(when-not (or (empty? vss)
(-> vss first empty?))
(binary-search-comparator
vss
(fn [row]
(let [f (first row)
l (peek row)]
(cond
(< v f) -1
(<= f v l) 0
(< l v) 1))))))
(defn sorted-matrix-search
"find index of 'v in 'matrix"
[matrix v]
(when-let [row-index (binary-search-matrix matrix v)]
(when-let [col-index (binary-search (nth matrix row-index) v)]
[row-index col-index])))
(t/deftest test
(t/are [vs v i] (= i (binary-search vs v))
[] 0 nil
[0] 0 0)
(let [test-vs (vec (range 100))]
(doseq [i (range 100)]
(t/is (= i (binary-search test-vs i)))))
(t/are [vss v i] (= i (binary-search-matrix vss v))
[] 0 nil
[[1]] 0 nil
[[1]] 1 0
[[1 2 3]
[4 5 6]
[7 8 9]] 1 0
[[1 2 3]
[4 5 6]
[7 8 9]] 6 1
[[1 2 3]
[4 5 6]
[7 8 9]] 7 2
[[1 2 3]
[4 5 6]
[7 8 9]] 0 nil)
(t/are [matrix v expected] (= expected (sorted-matrix-search matrix v))
[] 0 nil
[[1]] 0 nil
[[1]] 1 [0 0]
[[1 2 3]
[4 5 6]
[7 8 9]] 1 [0 0]
[[1 2 3]
[4 5 6]
[7 8 9]] 6 [1 2]
[[1 2 3]
[4 5 6]
[7 8 9]] 7 [2 0]
[[1 2 3]
[4 5 6]
[7 8 9]] 0 nil
[[1 2 3 4]
[5 6 7 8]
[9 10 11 12]] 8 [1 3]))
(t/run-tests *ns*)