Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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