Skip to content

Commit

Permalink
Add problem 2019: The Score of Students Solving Math Expression
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Sep 17, 2024
1 parent bfd9ed5 commit a4184ab
Show file tree
Hide file tree
Showing 3 changed files with 153 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 @@ -1504,6 +1504,7 @@ pub mod problem_2014_longest_subsequence_repeated_k_times;
pub mod problem_2016_maximum_difference_between_increasing_elements;
pub mod problem_2017_grid_game;
pub mod problem_2018_check_if_word_can_be_placed_in_crossword;
pub mod problem_2019_the_score_of_students_solving_math_expression;
pub mod problem_2022_convert_1d_array_into_2d_array;
pub mod problem_2023_number_of_pairs_of_strings_with_concatenation_equal_to_target;
pub mod problem_2024_maximize_the_confusion_of_an_exam;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
pub struct Solution;

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

impl Solution {
fn evaluate(s: &[u8]) -> u16 {
let (&first, rest) = s.split_first().unwrap();
let mut result = 0;
let mut term = u16::from(first - b'0');

for window in rest.chunks_exact(2) {
let [operator, rhs]: [_; 2] = window.try_into().ok().unwrap();
let rhs = u16::from(rhs) - u16::from(b'0');

if operator == b'+' {
result += term;
term = rhs;
} else {
term *= rhs;
}
}

result + term
}

pub fn score_of_students(s: String, answers: Vec<i32>) -> i32 {
let s = s.as_bytes();
let n = s.len() / 2 + 1;
let correct_answer = Self::evaluate(s);
let mut cache = vec![Vec::new(); n * n];
let mut values_set = [false; 1001];

for (&c, values) in s.iter().step_by(2).zip(&mut cache) {
values.push(u16::from(c - b'0'));
}

for operators in 1..n {
for start in 0..n - operators {
let mut values = Vec::new();

for left_operators in 0..operators {
let left = &*cache[n * left_operators + start];
let right = &*cache[n * (operators - 1 - left_operators) + start + left_operators + 1];

if s[(start + left_operators) * 2 + 1] == b'+' {
for &lhs in left {
for &rhs in right {
let x = lhs + rhs;

if let Some(state @ false) = values_set.get_mut(usize::from(x)) {
*state = true;
values.push(x);
}
}
}
} else {
for &lhs in left {
for &rhs in right {
if let Some(x) = lhs.checked_mul(rhs) {
if let Some(state @ false) = values_set.get_mut(usize::from(x)) {
*state = true;
values.push(x);
}
}
}
}
}
}

for &value in &values {
values_set[usize::from(value)] = false;
}

cache[n * operators + start] = values;
}
}

for &value in &cache[n * (n - 1)] {
values_set[usize::from(value)] = true;
}

drop(cache);

answers
.iter()
.map(|&answer| {
let answer = answer as u16;

if answer == correct_answer {
5
} else if values_set[usize::from(answer)] {
2
} else {
0
}
})
.sum()
}
}

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

impl super::Solution for Solution {
fn score_of_students(s: String, answers: Vec<i32>) -> i32 {
Self::score_of_students(s, answers)
}
}

#[cfg(test)]
mod tests {
#[test]
fn test_solution() {
super::super::tests::run::<super::Solution>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
pub mod dynamic_programming;

pub trait Solution {
fn score_of_students(s: String, answers: Vec<i32>) -> i32;
}

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

pub fn run<S: Solution>() {
let test_cases = [
(("7+3*1*2", &[20, 13, 42] as &[_]), 7),
(("3+5*2", &[13, 0, 10, 13, 13, 16, 16]), 19),
(("6+0*1", &[12, 9, 6, 4, 8, 6]), 10),
(
(
"6+3*6+2*9+9*4+9*9+5*9+6",
&[
512, 210, 210, 594, 210, 875, 762, 210, 210, 270, 342, 330, 210, 168, 767, 22, 462, 634, 194,
210, 552, 210, 210, 384, 210, 348, 210, 267, 553, 139, 210, 389, 614, 210, 825, 234, 900, 435,
210, 699, 454, 504, 300, 210, 210, 210, 215, 984, 210, 522, 943, 654, 793, 714, 870, 693, 210,
686, 210, 720, 153, 210, 957, 510, 210, 810, 210, 846, 714, 528, 942, 210, 342, 974, 210, 71,
906, 402, 726, 924, 388, 696, 210, 366, 210, 888, 825, 210, 210, 210, 654, 996, 846, 559, 210,
492, 210, 698, 210, 856, 576, 324, 822, 894, 666, 210, 935, 210, 840, 45, 641, 210, 210, 588,
708, 966, 462, 300, 210, 759, 480, 210,
],
),
291,
),
];

for ((s, answers), expected) in test_cases {
assert_eq!(S::score_of_students(s.to_string(), answers.to_vec()), expected);
}
}
}

0 comments on commit a4184ab

Please sign in to comment.