Skip to content

Commit

Permalink
Add problem 2172: Maximum AND Sum of Array
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Oct 5, 2024
1 parent 19f170b commit 40d21e3
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
82 changes: 82 additions & 0 deletions src/problem_2172_maximum_and_sum_of_array/dynamic_programming.rs
Original file line number Diff line number Diff line change
@@ -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<i32>, 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<i32>, num_slots: i32) -> i32 {
Self::maximum_and_sum(nums, num_slots)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
103 changes: 103 additions & 0 deletions src/problem_2172_maximum_and_sum_of_array/dynamic_programming_2.rs
Original file line number Diff line number Diff line change
@@ -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<i32>, 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<i32>, num_slots: i32) -> i32 {
Self::maximum_and_sum(nums, num_slots)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
24 changes: 24 additions & 0 deletions src/problem_2172_maximum_and_sum_of_array/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pub mod dynamic_programming;
pub mod dynamic_programming_2;

pub trait Solution {
fn maximum_and_sum(nums: Vec<i32>, num_slots: i32) -> i32;
}

#[cfg(test)]
mod tests {
use super::Solution;

pub fn run<S: Solution>() {
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);
}
}
}

0 comments on commit 40d21e3

Please sign in to comment.