Skip to content

Commit

Permalink
Add problem 2232: Minimize Result by Adding Parentheses to Expression
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh committed Sep 2, 2024
1 parent c4b5fe0 commit 096e256
Show file tree
Hide file tree
Showing 3 changed files with 144 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 @@ -1627,6 +1627,7 @@ pub mod problem_2224_minimum_number_of_operations_to_convert_time;
pub mod problem_2225_find_players_with_zero_or_one_losses;
pub mod problem_2226_maximum_candies_allocated_to_k_children;
pub mod problem_2231_largest_number_after_digit_swaps_by_parity;
pub mod problem_2232_minimize_result_by_adding_parentheses_to_expression;
pub mod problem_2233_maximum_product_after_k_increments;
pub mod problem_2235_add_two_integers;
pub mod problem_2236_root_equals_sum_of_children;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
pub struct Solution;

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

impl Solution {
pub fn minimize_result(expression: String) -> String {
let expression = expression.into_bytes();
let plus_position = expression.iter().position(|&c| c == b'+').unwrap();
let left = &expression[..plus_position];
let right = &expression[plus_position + 1..];
let mut left_pairs = [(0, 0); 8];
let mut right_pairs = [(0, 0); 8];

assert!(matches!((left.len(), right.len()), (1..=8, 1..=8)));

// Fill part 1.

let mut number = 0;

left_pairs[0].0 = 1;

for ((target, _), &digit) in left_pairs[1..].iter_mut().zip(left) {
number = number * 10 + u32::from(digit - b'0');
*target = number;
}

// Fill part 2.

let mut number = 0;
let mut base = 1;

for ((_, target), &digit) in left_pairs.iter_mut().zip(left).rev() {
number += u32::from(digit - b'0') * base;
*target = number;
base *= 10;
}

// Fill part 3.

let mut number = 0;

for ((target, _), &digit) in right_pairs.iter_mut().zip(right) {
number = number * 10 + u32::from(digit - b'0');
*target = number;
}

// Fill part 4.

let mut number = 0;
let mut base = 1;

for ((_, target), &digit) in right_pairs.iter_mut().zip(&right[1..]).rev() {
number += u32::from(digit - b'0') * base;
*target = number;
base *= 10;
}

right_pairs[right.len() - 1].1 = 1;

// Check all combinations.

let mut min = u32::MAX;
let mut split = (0, 0);

for (i, &(part_1, part_2)) in (0..).zip(&left_pairs[..left.len()]) {
for (j, &(part_3, part_4)) in (1..).zip(&right_pairs[..right.len()]) {
let value = part_1 * (part_2 + part_3) * part_4;

if value < min {
min = value;
split = (i, j);
}
}
}

let (part_1, part_2) = left.split_at(split.0);
let (part_3, part_4) = right.split_at(split.1);
let mut result = Vec::with_capacity(expression.len() + 2);

result.extend(part_1);
result.push(b'(');
result.extend(part_2);
result.push(b'+');
result.extend(part_3);
result.push(b')');
result.extend(part_4);

String::from_utf8(result).unwrap()
}
}

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

impl super::Solution for Solution {
fn minimize_result(expression: String) -> String {
Self::minimize_result(expression)
}
}

#[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 brute_force;

pub trait Solution {
fn minimize_result(expression: String) -> String;
}

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

pub fn run<S: Solution>() {
let test_cases = [("247+38", 170), ("12+34", 20), ("999+999", 1998)];

for (expression, expected) in test_cases {
let result = S::minimize_result(expression.to_string());
let result_middle = result.find('+').unwrap();
let left = &result[..result_middle];
let left_split = left.find('(').unwrap();
let left_left = &left[..left_split];
let left_right = &left[left_split + 1..];
let right = &result[result_middle + 1..];
let right_split = right.find(')').unwrap();
let right_left = &right[..right_split];
let right_right = &right[right_split + 1..];

assert_eq!(format!("{left_left}{left_right}+{right_left}{right_right}"), expression);

let parse = |s: &str| s.parse::<u32>().unwrap();
let parse_outer = |s: &str| if s.is_empty() { 1_u32 } else { s.parse().unwrap() };

assert_eq!(
parse_outer(left_left) * (parse(left_right) + parse(right_left)) * parse_outer(right_right),
expected,
);
}
}
}

0 comments on commit 096e256

Please sign in to comment.