Skip to content

Commit

Permalink
Add problem 1563: Stone Game V
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Jul 9, 2023
1 parent daa46ff commit 834d795
Show file tree
Hide file tree
Showing 3 changed files with 122 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 @@ -1292,6 +1292,7 @@ pub mod problem_1559_detect_cycles_in_2d_grid;
pub mod problem_1560_most_visited_sector_in_a_circular_track;
pub mod problem_1561_maximum_number_of_coins_you_can_get;
pub mod problem_1562_find_latest_group_of_size_m;
pub mod problem_1563_stone_game_v;
pub mod problem_1566_detect_pattern_of_length_m_repeated_k_or_more_times;
pub mod problem_1567_maximum_length_of_subarray_with_positive_product;
pub mod problem_1572_matrix_diagonal_sum;
Expand Down
96 changes: 96 additions & 0 deletions src/problem_1563_stone_game_v/dynamic_programming.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
pub struct Solution;

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl Solution {
pub fn stone_game_v(stone_value: Vec<i32>) -> i32 {
// Calculate sum.

let mut sums = stone_value;
let sums = sums.as_mut_slice();
let n = sums.len();
let mut cache = vec![(0_u32, 0_u32, 0_u32); n * n].into_boxed_slice();

let mut sum = 0;

for (sum_slot, cache_slot) in sums.iter_mut().zip(&mut *cache) {
cache_slot.1 = *sum_slot as _;
cache_slot.2 = *sum_slot as _;

sum += *sum_slot;
*sum_slot = sum;
}

// Dynamic programming.

for length in 2..=n {
let mut split = 0;

for start in 0..=n - length {
let end = start + length;
let start_sum = sums.get(start.wrapping_sub(1)).copied().unwrap_or(0) as u32;
let end_sum = sums[end - 1] as u32;

// Find the split point where.

let mut split_sum_times_2;
let max_split_sum_times_2 = start_sum + end_sum;

while {
split_sum_times_2 = sums[split] as u32 * 2;

split_sum_times_2 < max_split_sum_times_2
} {
split += 1;
}

// Calculate the best score.

let left_candidate = {
let left_end = split + usize::from(split_sum_times_2 == max_split_sum_times_2);

if left_end == start {
0
} else {
cache[n * (left_end - start - 1) + start].1
}
};

let right_candidate = {
let right_start = split + 1;

if right_start == end {
0
} else {
cache[n * (end - right_start - 1) + right_start].2
}
};

let score = left_candidate.max(right_candidate);
let new_alt_score = score + (end_sum - start_sum);
let max_left_alt_score = cache[n * (length - 2) + start].1.max(new_alt_score);
let max_right_alt_score = cache[n * (length - 2) + start + 1].2.max(new_alt_score);

cache[n * (length - 1) + start] = (score, max_left_alt_score, max_right_alt_score);
}
}

cache[n * (n - 1)].0 as _
}
}

// ------------------------------------------------------ snip ------------------------------------------------------ //

impl super::Solution for Solution {
fn stone_game_v(stone_value: Vec<i32>) -> i32 {
Self::stone_game_v(stone_value)
}
}

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

pub trait Solution {
fn stone_game_v(stone_value: Vec<i32>) -> i32;
}

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

pub fn run<S: Solution>() {
let test_cases = [
(&[6, 2, 3, 4, 5, 5] as &[_], 18),
(&[7, 7, 7, 7, 7, 7, 7], 28),
(&[4], 0),
(&[9, 8, 2, 4, 6, 3, 5, 1, 7], 34),
(&[98, 77, 24, 49, 6, 12, 2, 44, 51, 96], 330),
(&[10, 9, 8, 7, 6, 5, 4, 3, 2, 1], 37),
];

for (stone_value, expected) in test_cases {
assert_eq!(S::stone_game_v(stone_value.to_vec()), expected);
}
}
}

0 comments on commit 834d795

Please sign in to comment.