diff --git a/src/lib.rs b/src/lib.rs index 2c402e47..957456d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1358,6 +1358,7 @@ pub mod problem_1648_sell_diminishing_valued_colored_balls; pub mod problem_1649_create_sorted_array_through_instructions; pub mod problem_1652_defuse_the_bomb; pub mod problem_1653_minimum_deletions_to_make_string_balanced; +pub mod problem_1655_distribute_repeating_integers; pub mod problem_1656_design_an_ordered_stream; pub mod problem_1657_determine_if_two_strings_are_close; pub mod problem_1658_minimum_operations_to_reduce_x_to_zero; diff --git a/src/problem_1655_distribute_repeating_integers/dynamic_programming.rs b/src/problem_1655_distribute_repeating_integers/dynamic_programming.rs new file mode 100644 index 00000000..9dee5053 --- /dev/null +++ b/src/problem_1655_distribute_repeating_integers/dynamic_programming.rs @@ -0,0 +1,96 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +use std::mem; + +impl Solution { + fn count_nums(nums: Vec) -> Box<[u32]> { + let mut counts = [0; 1000]; + let mut unique_numbers = Vec::with_capacity(50); + + for num in nums { + let index = num as u32 as usize - 1; + let count = &mut counts[index]; + + if *count == 0 { + unique_numbers.push(index as _); + } + + *count += 1; + } + + let mut unique_numbers = unique_numbers.into_boxed_slice(); + + for slot in &mut *unique_numbers { + *slot = counts[*slot as usize]; + } + + unique_numbers + } + + fn get_quantity_sums(value: Vec) -> ([u32; 1024], usize) { + let n = value.len(); + let mut result = [0_u32; 1024]; + + assert!(n <= 10); + + for bits in 1..(1 << n) { + result[bits] = result[bits & (bits - 1)] + value[bits.trailing_zeros() as usize] as u32; + } + + (result, n) + } + + pub fn can_distribute(nums: Vec, quantity: Vec) -> bool { + let counts = Self::count_nums(nums); + let (quantity_sums, n) = Self::get_quantity_sums(quantity); + let cache_size = 1 << n; + let mut buffer = [false; 2048]; + let (mut cache, mut temp) = buffer[..cache_size * 2].split_at_mut(cache_size); + + cache[0] = true; + + for &count in &*counts { + for (target_bits, target) in (0_u16..).zip(&mut *temp) { + let mut selected_bits = target_bits; + + // See . + + *target = loop { + if quantity_sums[usize::from(selected_bits)] <= count + && cache[usize::from(target_bits ^ selected_bits)] + { + break true; + } + + if selected_bits == 0 { + break false; + } + + selected_bits = (selected_bits - 1) & target_bits; + }; + } + + mem::swap(&mut cache, &mut temp); + } + + *cache.last().unwrap() + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn can_distribute(nums: Vec, quantity: Vec) -> bool { + Self::can_distribute(nums, quantity) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_1655_distribute_repeating_integers/mod.rs b/src/problem_1655_distribute_repeating_integers/mod.rs new file mode 100644 index 00000000..7c53c870 --- /dev/null +++ b/src/problem_1655_distribute_repeating_integers/mod.rs @@ -0,0 +1,36 @@ +pub mod dynamic_programming; + +pub trait Solution { + fn can_distribute(nums: Vec, quantity: Vec) -> bool; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + ((&[1, 2, 3, 4] as &[_], &[2] as &[_]), false), + ((&[1, 2, 3, 3], &[2]), true), + ((&[1, 1, 2, 2], &[2, 2]), true), + ( + ( + &[ + 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, + 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, + 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, + 39, 39, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, + ], + &[2, 2, 2, 2, 2, 2, 2, 2, 2, 3], + ), + false, + ), + ((&[1, 1, 2, 2, 1], &[2, 2, 1]), true), + ((&[1, 1, 1, 1, 2, 2, 2], &[3, 2, 2]), true), + ]; + + for ((nums, quantity), expected) in test_cases { + assert_eq!(S::can_distribute(nums.to_vec(), quantity.to_vec()), expected); + } + } +}