mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Improve code reuse
This commit is contained in:
@@ -2,35 +2,41 @@ use std::io::Read;
|
|||||||
|
|
||||||
use crate::common::Lines;
|
use crate::common::Lines;
|
||||||
use crate::Solution;
|
use crate::Solution;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
enum Op {
|
enum Op {
|
||||||
Addition,
|
Addition,
|
||||||
Multiplication,
|
Multiplication,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_brackets(with_brackets: &str) -> (&str, &str) {
|
fn extract_part(expression: &str) -> (&str, &str) {
|
||||||
let mut brackets = 1;
|
if expression.starts_with('(') {
|
||||||
|
let mut brackets = 1;
|
||||||
|
|
||||||
let mut end = None;
|
for (end, c) in expression.chars().enumerate().skip(1) {
|
||||||
|
match c {
|
||||||
|
'(' => brackets += 1,
|
||||||
|
')' => brackets -= 1,
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
for (i, c) in with_brackets.chars().enumerate().skip(1) {
|
if brackets == 0 {
|
||||||
match c {
|
return (
|
||||||
'(' => brackets += 1,
|
// Include the opening bracket for easier detection
|
||||||
')' => brackets -= 1,
|
&expression[..end],
|
||||||
_ => {}
|
expression.get((end + 2)..).unwrap_or(""),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if brackets == 0 {
|
panic!("Unmatched brackets: {}", expression);
|
||||||
end = Some(i);
|
} else if let Some(pos) = expression.find(' ') {
|
||||||
break;
|
(
|
||||||
}
|
&expression[..pos],
|
||||||
|
expression.get((pos + 1)..).unwrap_or(""),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(expression, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
let end = end.expect("Unmatched brackets");
|
|
||||||
let next_start = with_brackets.len().min(end + 2);
|
|
||||||
|
|
||||||
(&with_brackets[1..end], &with_brackets[next_start..])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_value(expression: &str) -> u64 {
|
fn compute_value(expression: &str) -> u64 {
|
||||||
@@ -38,42 +44,28 @@ fn compute_value(expression: &str) -> u64 {
|
|||||||
let mut value = 0;
|
let mut value = 0;
|
||||||
let mut op = None;
|
let mut op = None;
|
||||||
|
|
||||||
let mut apply_value = |n, op| match op {
|
|
||||||
Some(Op::Addition) => value += n,
|
|
||||||
Some(Op::Multiplication) => value *= n,
|
|
||||||
None => value = n,
|
|
||||||
};
|
|
||||||
|
|
||||||
while !remainder.is_empty() {
|
while !remainder.is_empty() {
|
||||||
let pos = remainder.find(' ');
|
let (part, rest) = extract_part(remainder);
|
||||||
|
remainder = rest;
|
||||||
|
|
||||||
let part = if let Some(pos) = pos {
|
let n = match part.chars().next().unwrap() {
|
||||||
&remainder[..pos]
|
'+' => {
|
||||||
} else {
|
op = Some(Op::Addition);
|
||||||
remainder
|
|
||||||
};
|
|
||||||
|
|
||||||
match part.chars().next().unwrap() {
|
|
||||||
'+' => op = Some(Op::Addition),
|
|
||||||
'*' => op = Some(Op::Multiplication),
|
|
||||||
'(' => {
|
|
||||||
let (in_brackets, rest) = extract_brackets(remainder);
|
|
||||||
remainder = rest;
|
|
||||||
let n = compute_value(in_brackets);
|
|
||||||
|
|
||||||
apply_value(n, op);
|
|
||||||
// Skip the remainder update
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
c if c.is_ascii_digit() => {
|
'*' => {
|
||||||
let n = part.parse().unwrap();
|
op = Some(Op::Multiplication);
|
||||||
apply_value(n, op);
|
continue;
|
||||||
}
|
}
|
||||||
_ => panic!("Not a valid expression part {}", part),
|
'(' => compute_value(&part[1..]),
|
||||||
}
|
_ => part.parse().unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
let pos = pos.map(|n| n + 1).unwrap_or_else(|| remainder.len());
|
match op {
|
||||||
remainder = &remainder[pos..];
|
Some(Op::Addition) => value += n,
|
||||||
|
Some(Op::Multiplication) => value *= n,
|
||||||
|
None => value = n,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value
|
value
|
||||||
@@ -85,46 +77,31 @@ fn compute_value2(expression: &str) -> u64 {
|
|||||||
let mut result = 1;
|
let mut result = 1;
|
||||||
let mut op = None;
|
let mut op = None;
|
||||||
|
|
||||||
let mut apply_value = |n, op| match op {
|
|
||||||
Some(Op::Addition) => value += n,
|
|
||||||
Some(Op::Multiplication) => {
|
|
||||||
result *= value;
|
|
||||||
value = n;
|
|
||||||
}
|
|
||||||
None => value = n,
|
|
||||||
};
|
|
||||||
|
|
||||||
while !remainder.is_empty() {
|
while !remainder.is_empty() {
|
||||||
let pos = remainder.find(' ');
|
let (part, rest) = extract_part(remainder);
|
||||||
|
remainder = rest;
|
||||||
|
|
||||||
let part = if let Some(pos) = pos {
|
let n = match part.chars().next().unwrap() {
|
||||||
&remainder[..pos]
|
'+' => {
|
||||||
} else {
|
op = Some(Op::Addition);
|
||||||
remainder
|
|
||||||
};
|
|
||||||
|
|
||||||
match part.chars().next().unwrap() {
|
|
||||||
'+' => op = Some(Op::Addition),
|
|
||||||
'*' => op = Some(Op::Multiplication),
|
|
||||||
'(' => {
|
|
||||||
let (in_brackets, rest) = extract_brackets(remainder);
|
|
||||||
remainder = rest;
|
|
||||||
let n = compute_value2(in_brackets);
|
|
||||||
|
|
||||||
apply_value(n, op);
|
|
||||||
// Skip the remainder update
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
c if c.is_ascii_digit() => {
|
'*' => {
|
||||||
let n = part.parse().unwrap();
|
op = Some(Op::Multiplication);
|
||||||
|
continue;
|
||||||
apply_value(n, op);
|
|
||||||
}
|
}
|
||||||
_ => panic!("Not a valid expression part {}", part),
|
'(' => compute_value2(&part[1..]),
|
||||||
}
|
_ => part.parse().unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
let pos = pos.map(|n| n + 1).unwrap_or_else(|| remainder.len());
|
match op {
|
||||||
remainder = &remainder[pos..];
|
Some(Op::Addition) => value += n,
|
||||||
|
Some(Op::Multiplication) => {
|
||||||
|
result *= value;
|
||||||
|
value = n;
|
||||||
|
}
|
||||||
|
None => value = n,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result * value
|
result * value
|
||||||
|
|||||||
Reference in New Issue
Block a user