Skip to content

Commit f90fa80

Browse files
committed
feat(moore_voting)!: generic, refactor, const, etc...
1 parent 6e42c38 commit f90fa80

File tree

2 files changed

+97
-12
lines changed

2 files changed

+97
-12
lines changed

src/searching/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ pub use self::jump_search::jump_search;
2424
pub use self::kth_smallest::kth_smallest;
2525
pub use self::kth_smallest_heap::kth_smallest_heap;
2626
pub use self::linear_search::linear_search;
27-
pub use self::moore_voting::moore_voting;
27+
pub use self::moore_voting::moore_voting_2pass;
28+
pub use self::moore_voting::moore_voting_2pass_c;
29+
pub use self::moore_voting::moore_voting_it;
2830
pub use self::quick_select::quick_select;
2931
pub use self::saddleback_search::saddleback_search;
3032
pub use self::ternary_search::ternary_search;

src/searching/moore_voting.rs

Lines changed: 94 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
(assumed: all elements are >0)
1313
1414
Initialisation: ele=0, cnt=0
15-
Loop beings.
15+
Loop begins.
1616
1717
loop 1: arr[0]=9
1818
ele = 9
@@ -41,12 +41,26 @@
4141
4242
*/
4343

44-
pub fn moore_voting(arr: &[i32]) -> i32 {
45-
let n = arr.len();
46-
let mut cnt = 0; // initializing cnt
47-
let mut ele = 0; // initializing ele
44+
// boilerplate, because `==` isn't `const` yet
45+
const fn eq_s(a: &[u8], b: &[u8]) -> bool {
46+
if a.len() != b.len() {
47+
return false;
48+
}
49+
let mut i = 0;
50+
while i < a.len() {
51+
if a[i] != b[i] {
52+
return false;
53+
}
54+
i += 1;
55+
}
56+
true
57+
}
58+
59+
pub fn moore_voting_2pass<T: Eq>(arr: &[T]) -> Option<&T> {
60+
let mut ele = arr.first()?;
61+
let mut cnt = 0;
4862

49-
for &item in arr.iter() {
63+
for item in arr.iter() {
5064
if cnt == 0 {
5165
cnt = 1;
5266
ele = item;
@@ -57,24 +71,93 @@ pub fn moore_voting(arr: &[i32]) -> i32 {
5771
}
5872
}
5973

60-
let cnt_check = arr.iter().filter(|&&x| x == ele).count();
74+
let cnt_check = arr.iter().filter(|&x| x == ele).count();
6175

76+
let n = arr.len();
6277
if cnt_check > (n / 2) {
63-
ele
78+
Some(ele)
6479
} else {
65-
-1
80+
None
6681
}
6782
}
6883

84+
pub const fn moore_voting_2pass_c<'a>(arr: &[&'a [u8]]) -> Option<&'a [u8]> {
85+
let n = arr.len();
86+
if n == 0 {
87+
return None;
88+
}
89+
let mut cnt: usize = 1;
90+
let mut ele = arr[0];
91+
let mut i = 1;
92+
while i < n {
93+
if cnt == 0 {
94+
cnt = 1;
95+
ele = arr[i];
96+
} else if eq_s(arr[i], ele) {
97+
cnt += 1;
98+
} else {
99+
cnt -= 1;
100+
}
101+
i += 1;
102+
}
103+
104+
let mut cnt_check = 0;
105+
let mut i = 0;
106+
while i < n {
107+
if eq_s(arr[i], ele) {
108+
cnt_check += 1;
109+
}
110+
i += 1;
111+
}
112+
113+
if cnt_check > (n / 2) {
114+
Some(ele)
115+
} else {
116+
None
117+
}
118+
}
119+
120+
/// Returns `None` only if `i` is empty.
121+
/// If there are multiple majorities, anyone could be returned.
122+
///
123+
/// # Panics
124+
/// In debug-mode, if the internal majority-counter overflows.
125+
/// The counter is `usize`, so it'll **never** overlow if `i` is a slice.
126+
///
127+
/// Even if `i` is infinite, the counter might never overflow;
128+
/// consider this:
129+
/// ```
130+
/// core::iter::successors(Some(false), |b| Some(!b));
131+
/// ```
132+
/// This is equivalent to the sequence `1-1+1-1...`
133+
pub fn moore_voting_it<T: Eq, I: IntoIterator<Item = T>>(it: I) -> Option<T> {
134+
let mut it = it.into_iter();
135+
let first = it.next()?;
136+
Some(
137+
it.fold((1_usize, first), |(cnt, ele), item| {
138+
if cnt == 0 {
139+
(1, item)
140+
} else if item == ele {
141+
(cnt + 1, ele)
142+
} else {
143+
(cnt - 1, ele)
144+
}
145+
})
146+
.1,
147+
)
148+
}
149+
69150
#[cfg(test)]
70151
mod tests {
71152
use super::*;
72153

73154
#[test]
74155
fn test_moore_voting() {
75156
let arr1: Vec<i32> = vec![9, 1, 8, 1, 1];
76-
assert!(moore_voting(&arr1) == 1);
157+
assert!(moore_voting_2pass(&arr1) == Some(&1));
158+
assert!(moore_voting_it(arr1) == Some(1));
77159
let arr2: Vec<i32> = vec![1, 2, 3, 4];
78-
assert!(moore_voting(&arr2) == -1);
160+
assert!(moore_voting_2pass(&arr2) == None);
161+
assert!(moore_voting_it(arr2) == None);
79162
}
80163
}

0 commit comments

Comments
 (0)