From d035d2c305714fa67b06754749b284babb993eab Mon Sep 17 00:00:00 2001 From: Rudxain <76864299+Rudxain@users.noreply.github.com> Date: Thu, 9 Apr 2026 21:08:38 -0400 Subject: [PATCH] feat(moore_voting)!: generic, refactor, const, etc... --- src/searching/mod.rs | 4 +- src/searching/moore_voting.rs | 104 ++++++++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 12 deletions(-) diff --git a/src/searching/mod.rs b/src/searching/mod.rs index 94f65988195..adbf0a271b9 100644 --- a/src/searching/mod.rs +++ b/src/searching/mod.rs @@ -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; diff --git a/src/searching/moore_voting.rs b/src/searching/moore_voting.rs index 8acf0dd8b36..4bece720259 100644 --- a/src/searching/moore_voting.rs +++ b/src/searching/moore_voting.rs @@ -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 @@ -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(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; @@ -57,15 +71,82 @@ 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>(it: I) -> Option { + 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::*; @@ -73,8 +154,9 @@ mod tests { #[test] fn test_moore_voting() { let arr1: Vec = 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 = vec![1, 2, 3, 4]; - assert!(moore_voting(&arr2) == -1); + assert_eq!(moore_voting_2pass(&arr2), None); } }