From 40d21e34d23ca47b19b672eee9e4fd7ffba06125 Mon Sep 17 00:00:00 2001 From: EFanZh Date: Sat, 5 Oct 2024 09:43:02 +0800 Subject: [PATCH] Add problem 2172: Maximum AND Sum of Array --- src/lib.rs | 1 + .../dynamic_programming.rs | 82 ++++++++++++++ .../dynamic_programming_2.rs | 103 ++++++++++++++++++ .../mod.rs | 24 ++++ 4 files changed, 210 insertions(+) create mode 100644 src/problem_2172_maximum_and_sum_of_array/dynamic_programming.rs create mode 100644 src/problem_2172_maximum_and_sum_of_array/dynamic_programming_2.rs create mode 100644 src/problem_2172_maximum_and_sum_of_array/mod.rs diff --git a/src/lib.rs b/src/lib.rs index db03da4c..ba4547dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1620,6 +1620,7 @@ pub mod problem_2167_minimum_time_to_remove_all_cars_containing_illegal_goods; pub mod problem_2169_count_operations_to_obtain_zero; pub mod problem_2170_minimum_operations_to_make_the_array_alternating; pub mod problem_2171_removing_minimum_number_of_magic_beans; +pub mod problem_2172_maximum_and_sum_of_array; pub mod problem_2176_count_equal_and_divisible_pairs_in_an_array; pub mod problem_2177_find_three_consecutive_integers_that_sum_to_a_given_number; pub mod problem_2178_maximum_split_of_positive_even_integers; diff --git a/src/problem_2172_maximum_and_sum_of_array/dynamic_programming.rs b/src/problem_2172_maximum_and_sum_of_array/dynamic_programming.rs new file mode 100644 index 00000000..278cbfb8 --- /dev/null +++ b/src/problem_2172_maximum_and_sum_of_array/dynamic_programming.rs @@ -0,0 +1,82 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + fn count_numbers(mut x: u16) -> u8 { + let mut result = 0; + + while x != 0 { + let digit = x % 3; + + x /= 3; + + result += digit as u8; + } + + result + } + + pub fn maximum_and_sum(nums: Vec, num_slots: i32) -> i32 { + let n = nums.len() as u8; + let num_slots = num_slots as u32 as usize; + let configurations = u16::pow(3, num_slots as _); + let mut cache = vec![0_u8; usize::from(configurations)].into_boxed_slice(); + let mut result = 0; + + for configuration in 1..configurations { + let count = Self::count_numbers(configuration); + + if count > n { + continue; + } + + let num = nums[usize::from(count - 1)] as u8; + let mut iter = configuration; + let mut slot = 1; + let mut probe = 1; + let mut max = 0; + + loop { + let digit = iter % 3; + + iter /= 3; + + if digit != 0 { + max = max.max(cache[usize::from(configuration - probe)] + (slot & num)); + } + + if iter == 0 { + break; + } + + slot += 1; + probe *= 3; + } + + cache[usize::from(configuration)] = max; + + if count == n { + result = result.max(max); + } + } + + i32::from(result) + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn maximum_and_sum(nums: Vec, num_slots: i32) -> i32 { + Self::maximum_and_sum(nums, num_slots) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2172_maximum_and_sum_of_array/dynamic_programming_2.rs b/src/problem_2172_maximum_and_sum_of_array/dynamic_programming_2.rs new file mode 100644 index 00000000..79eb9555 --- /dev/null +++ b/src/problem_2172_maximum_and_sum_of_array/dynamic_programming_2.rs @@ -0,0 +1,103 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + fn combinations(n: u8, mut k: u8, base: u16, f: &mut impl FnMut(u16)) { + match k { + 0 => f(base), + 1 => { + let mut probe = 1; + + for _ in 0..n { + f(base + probe); + + probe *= 3; + } + } + _ => { + let mut start = k / 2; + let mut probe = u16::pow(3, u32::from(start)); + + k -= 1; + + for i in start..n { + Self::combinations(i, k, base + probe, f); + + probe *= 3; + } + + start = k / 2; + probe = u16::pow(3, u32::from(start)) * 2; + k -= 1; + + for i in start..n { + Self::combinations(i, k, base + probe, f); + + probe *= 3; + } + } + } + } + + pub fn maximum_and_sum(nums: Vec, num_slots: i32) -> i32 { + let n = nums.len() as u8; + let num_slots = num_slots as u32 as usize; + let configurations = u16::pow(3, num_slots as _); + let mut cache = vec![0_u8; usize::from(configurations)].into_boxed_slice(); + + (1..).zip(&nums).for_each(|(count, num)| { + let num = *num as u8; + + Self::combinations(num_slots as _, count, 0, &mut |configuration| { + let mut iter = configuration; + let mut slot = 1; + let mut probe = 1; + let mut max = 0; + + loop { + let digit = iter % 3; + + iter /= 3; + + if digit != 0 { + max = max.max(cache[usize::from(configuration - probe)] + (slot & num)); + } + + if iter == 0 { + break; + } + + slot += 1; + probe *= 3; + } + + cache[usize::from(configuration)] = max; + }); + }); + + let mut result = 0; + + Self::combinations(num_slots as _, n, 0, &mut |configuration| { + result = result.max(cache[usize::from(configuration)]); + }); + + i32::from(result) + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn maximum_and_sum(nums: Vec, num_slots: i32) -> i32 { + Self::maximum_and_sum(nums, num_slots) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2172_maximum_and_sum_of_array/mod.rs b/src/problem_2172_maximum_and_sum_of_array/mod.rs new file mode 100644 index 00000000..4e931f48 --- /dev/null +++ b/src/problem_2172_maximum_and_sum_of_array/mod.rs @@ -0,0 +1,24 @@ +pub mod dynamic_programming; +pub mod dynamic_programming_2; + +pub trait Solution { + fn maximum_and_sum(nums: Vec, num_slots: i32) -> i32; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + ((&[1, 2, 3, 4, 5, 6] as &[_], 3), 9), + ((&[1, 3, 10, 4, 7, 1], 9), 24), + ((&[10, 5, 3, 6, 11, 8, 8], 4), 16), + ((&[8, 13, 3, 15, 3, 15, 2, 15, 5, 7, 6], 8), 60), + ]; + + for ((nums, num_slots), expected) in test_cases { + assert_eq!(S::maximum_and_sum(nums.to_vec(), num_slots), expected); + } + } +}