diff --git a/src/lib.rs b/src/lib.rs index fa054406..eb7fb3ec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1651,6 +1651,7 @@ pub mod problem_2208_minimum_operations_to_halve_array_sum; pub mod problem_2209_minimum_white_tiles_after_covering_with_carpets; pub mod problem_2210_count_hills_and_valleys_in_an_array; pub mod problem_2211_count_collisions_on_a_road; +pub mod problem_2212_maximum_points_in_an_archery_competition; pub mod problem_2215_find_the_difference_of_two_arrays; pub mod problem_2216_minimum_deletions_to_make_array_beautiful; pub mod problem_2218_maximum_value_of_k_coins_from_piles; diff --git a/src/problem_2212_maximum_points_in_an_archery_competition/dynamic_programming.rs b/src/problem_2212_maximum_points_in_an_archery_competition/dynamic_programming.rs new file mode 100644 index 00000000..24e3895f --- /dev/null +++ b/src/problem_2212_maximum_points_in_an_archery_competition/dynamic_programming.rs @@ -0,0 +1,67 @@ +pub struct Solution; + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl Solution { + fn helper(num_arrows: u32, alice_arrows: &mut [i32; 12]) { + const CONFIGURATIONS: usize = 1 << 11; + + let mut arrow_sums = [0_u32; CONFIGURATIONS]; + let mut scores = [0_u8; CONFIGURATIONS]; + let mut max_score = 0; + let mut max_score_configuration = 0; + let mut max_score_arrows = 0; + + alice_arrows.iter_mut().for_each(|x| *x += 1); + + for configuration in 1..CONFIGURATIONS { + let i = configuration.trailing_zeros() as usize; + let prev = configuration & (configuration - 1); + let arrow_sum = arrow_sums[prev] + alice_arrows[i + 1] as u32; + + arrow_sums[configuration] = arrow_sum; + + let score = scores[prev] + i as u8 + 1; + + scores[configuration] = score; + + if arrow_sum <= num_arrows && score > max_score { + max_score = score; + max_score_configuration = configuration; + max_score_arrows = arrow_sum; + } + } + + alice_arrows[0] = (num_arrows - max_score_arrows) as _; + + alice_arrows[1..].iter_mut().enumerate().for_each(|(i, count)| { + if max_score_configuration & (1 << i) == 0 { + *count = 0; + } + }); + } + + pub fn maximum_bob_points(num_arrows: i32, alice_arrows: Vec) -> Vec { + let mut alice_arrows = alice_arrows; + + Self::helper(num_arrows as _, alice_arrows.as_mut_slice().try_into().ok().unwrap()); + + alice_arrows + } +} + +// ------------------------------------------------------ snip ------------------------------------------------------ // + +impl super::Solution for Solution { + fn maximum_bob_points(num_arrows: i32, alice_arrows: Vec) -> Vec { + Self::maximum_bob_points(num_arrows, alice_arrows) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_solution() { + super::super::tests::run::(); + } +} diff --git a/src/problem_2212_maximum_points_in_an_archery_competition/mod.rs b/src/problem_2212_maximum_points_in_an_archery_competition/mod.rs new file mode 100644 index 00000000..ed0091a5 --- /dev/null +++ b/src/problem_2212_maximum_points_in_an_archery_competition/mod.rs @@ -0,0 +1,33 @@ +pub mod dynamic_programming; + +pub trait Solution { + fn maximum_bob_points(num_arrows: i32, alice_arrows: Vec) -> Vec; +} + +#[cfg(test)] +mod tests { + use super::Solution; + + pub fn run() { + let test_cases = [ + ((9, [1, 1, 0, 1, 0, 0, 2, 1, 0, 1, 2, 0]), 47), + ((3, [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2]), 27), + ]; + + for ((num_arrows, alice_arrows), expected) in test_cases { + let result = S::maximum_bob_points(num_arrows, alice_arrows.to_vec()); + let result: &[_; 12] = result.as_slice().try_into().unwrap(); + + assert_eq!(result.iter().sum::(), num_arrows); + + assert_eq!( + (0..) + .zip(result.iter().zip(&alice_arrows)) + .fold(0, |score, (i, (bob_count, alice_count))| { + score + (if bob_count > alice_count { i } else { 0 }) + }), + expected, + ); + } + } +}