diff --git a/problems/reduce-array-size-to-the-half.rs b/problems/reduce-array-size-to-the-half.rs new file mode 100644 index 0000000..b6b67e9 --- /dev/null +++ b/problems/reduce-array-size-to-the-half.rs @@ -0,0 +1,89 @@ +use std::collections::BTreeMap; + +struct Accumulator { + removed: usize, + removed_distinct: i32, +} + +impl Accumulator { + fn new() -> Accumulator { + Accumulator { removed: 0, removed_distinct: 0 } + } + + fn update(self, length: usize, count: i32) -> Accumulator { + if 2 * self.removed < length { + Accumulator { + removed: self.removed + count as usize, + removed_distinct: self.removed_distinct + 1, + } + } else { + self + } + } +} + +impl Solution { + pub fn min_set_size(arr: Vec) -> i32 { + let mut counts = arr + .iter() + .fold(BTreeMap::::new(), |mut acc: BTreeMap, x: &i32| { + let current = *acc.get(x).unwrap_or(&0); + acc.insert(*x, current + 1); + + acc + }) + .iter() + .map(|(&x, &y)| { (x, y) }) + .collect::>(); + + counts + .sort_by(|&(_, y0), &(_, y1)| y1.cmp(&y0)); + + counts + .iter() + .fold(Accumulator::new(), |acc, &(_, count)| { + acc.update(arr.len(), count) + }).removed_distinct + } +} + +struct Solution {} + +fn main() { + println!("Hello, world!"); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_example() { + assert_eq!(Solution::min_set_size(vec![3, 3, 3, 3, 5, 5, 5, 2, 2, 7]), 2); + } + + #[test] + fn test_all_same() { + assert_eq!(Solution::min_set_size(vec![7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7]), 1); + } + + #[test] + fn test_remove_exact_half() { + assert_eq!(Solution::min_set_size(vec![1, 1, 2, 2]), 1); + } + + #[test] + fn test_remove_more_than_half() { + assert_eq!(Solution::min_set_size(vec![1, 1, 2, 2, 2]), 1); + } + + #[test] + fn test_all_distinct() { + assert_eq!(Solution::min_set_size(vec![1, 2, 3, 4, 5, 6, 7]), 4); + } + + #[test] + fn test_big_distinct() { + assert_eq!(Solution::min_set_size((1..=100).rev().collect()), 50); + } +}