-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.rs
More file actions
71 lines (60 loc) · 1.97 KB
/
search.rs
File metadata and controls
71 lines (60 loc) · 1.97 KB
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
pub fn lower_bound(range: std::ops::Range<usize>, prop: &dyn Fn(usize) -> bool) -> Option<usize> {
if prop(range.start) {
return Some(range.start);
}
let mut ng = range.start;
let mut ok = range.end;
while ok - ng > 1 {
let middle = ng + (ok - ng) / 2;
match prop(middle) {
true => ok = middle,
false => ng = middle,
}
}
match ok.eq(&range.end) {
true => None,
false => Some(ok),
}
}
#[cfg(test)]
mod test_lower_bound {
use crate::search::lower_bound;
#[test]
fn it_works() {
let vs: Vec<usize> = vec![1, 2, 3, 5, 7, 10];
assert_eq!(lower_bound(0..vs.len(), &|x| 1 <= vs[x]), Some(0));
assert_eq!(lower_bound(0..vs.len(), &|x| 2 <= vs[x]), Some(1));
assert_eq!(lower_bound(0..vs.len(), &|x| 3 <= vs[x]), Some(2));
assert_eq!(lower_bound(0..vs.len(), &|x| 7 <= vs[x]), Some(4));
assert_eq!(lower_bound(0..vs.len(), &|x| 10 <= vs[x]), Some(5));
assert_eq!(lower_bound(0..vs.len(), &|x| 100 <= vs[x]), None);
}
}
pub fn upper_bound(range: std::ops::Range<usize>, prop: &dyn Fn(usize) -> bool) -> Option<usize> {
if !prop(range.start) {
return None;
}
let mut ok = range.start;
let mut ng = range.end;
while ng - ok > 1 {
let middle = ok + (ng - ok) / 2;
match prop(middle) {
true => ok = middle,
false => ng = middle,
}
}
Some(ok)
}
#[cfg(test)]
mod test_upper_bound {
use crate::search::upper_bound;
#[test]
fn it_works() {
let vs: Vec<usize> = vec![1, 2, 3, 5, 7, 10];
assert_eq!(upper_bound(0..vs.len(), &|x| vs[x] < 1), None);
assert_eq!(upper_bound(0..vs.len(), &|x| vs[x] < 2), Some(0));
assert_eq!(upper_bound(0..vs.len(), &|x| vs[x] < 3), Some(1));
assert_eq!(upper_bound(0..vs.len(), &|x| vs[x] < 7), Some(3));
assert_eq!(upper_bound(0..vs.len(), &|x| vs[x] < 10), Some(4));
}
}