Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/searching/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ pub use self::jump_search::jump_search;
pub use self::kth_smallest::kth_smallest;
pub use self::kth_smallest_heap::kth_smallest_heap;
pub use self::linear_search::linear_search;
pub use self::moore_voting::moore_voting;
pub use self::moore_voting::moore_voting_2pass;
pub use self::moore_voting::moore_voting_2pass_c;
pub use self::moore_voting::moore_voting_it;
pub use self::quick_select::quick_select;
pub use self::saddleback_search::saddleback_search;
pub use self::ternary_search::ternary_search;
Expand Down
104 changes: 93 additions & 11 deletions src/searching/moore_voting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
(assumed: all elements are >0)

Initialisation: ele=0, cnt=0
Loop beings.
Loop begins.

loop 1: arr[0]=9
ele = 9
Expand Down Expand Up @@ -41,12 +41,26 @@

*/

pub fn moore_voting(arr: &[i32]) -> i32 {
let n = arr.len();
let mut cnt = 0; // initializing cnt
let mut ele = 0; // initializing ele
// boilerplate, because `==` isn't `const` yet
const fn eq_s(a: &[u8], b: &[u8]) -> bool {
if a.len() != b.len() {
return false;
}
let mut i = 0;
while i < a.len() {
if a[i] != b[i] {
return false;
}
i += 1;
}
true
}

pub fn moore_voting_2pass<T: Eq>(arr: &[T]) -> Option<&T> {
let mut ele = arr.first()?;
let mut cnt = 0;

for &item in arr.iter() {
for item in arr.iter() {
if cnt == 0 {
cnt = 1;
ele = item;
Expand All @@ -57,24 +71,92 @@ pub fn moore_voting(arr: &[i32]) -> i32 {
}
}

let cnt_check = arr.iter().filter(|&&x| x == ele).count();
let cnt_check = arr.iter().filter(|&x| x == ele).count();

let n = arr.len();
if cnt_check > (n / 2) {
ele
Some(ele)
} else {
-1
None
}
}

pub const fn moore_voting_2pass_c<'a>(arr: &[&'a [u8]]) -> Option<&'a [u8]> {
let n = arr.len();
if n == 0 {
return None;
}
let mut cnt: usize = 1;
let mut ele = arr[0];
let mut i = 1;
while i < n {
if cnt == 0 {
cnt = 1;
ele = arr[i];
} else if eq_s(arr[i], ele) {
cnt += 1;
} else {
cnt -= 1;
}
i += 1;
}

let mut cnt_check = 0;
let mut i = 0;
while i < n {
if eq_s(arr[i], ele) {
cnt_check += 1;
}
i += 1;
}

if cnt_check > (n / 2) {
Some(ele)
} else {
None
}
}

/// Returns `None` only if `i` is empty.
/// If there are multiple majorities, anyone could be returned.
///
/// # Panics
/// In debug-mode, if the internal majority-counter overflows.
/// The counter is `usize`, so it'll **never** overlow if `i` is a slice.
///
/// Even if `i` is infinite, the counter might never overflow;
/// consider this:
/// ```
/// core::iter::successors(Some(false), |b| Some(!b));
/// ```
/// This is equivalent to the sequence `1-1+1-1...`
pub fn moore_voting_it<T: Eq, I: IntoIterator<Item = T>>(it: I) -> Option<T> {
let mut it = it.into_iter();
let first = it.next()?;
Some(
it.fold((1_usize, first), |(cnt, ele), item| {
if cnt == 0 {
(1, item)
} else if item == ele {
(cnt + 1, ele)
} else {
(cnt - 1, ele)
}
})
.1,
)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_moore_voting() {
let arr1: Vec<i32> = vec![9, 1, 8, 1, 1];
assert!(moore_voting(&arr1) == 1);
assert_eq!(moore_voting_2pass(&arr1), Some(&1));
assert_eq!(moore_voting_it(arr1), Some(1));
let arr2: Vec<i32> = vec![1, 2, 3, 4];
assert!(moore_voting(&arr2) == -1);
assert_eq!(moore_voting_2pass(&arr2), None);
}
}
Loading