114 lines
3.0 KiB
Rust
114 lines
3.0 KiB
Rust
use std::error::Error;
|
|
use std::fs::File;
|
|
use std::io::{self, BufRead};
|
|
use std::vec::Vec;
|
|
|
|
fn extract_paren_expression(input: &str) -> String {
|
|
let mut res: String = "".to_string();
|
|
let mut open_count = 1;
|
|
let mut close_count = 0;
|
|
|
|
for c in input[1..].chars() {
|
|
match c {
|
|
'(' => open_count += 1,
|
|
')' => {
|
|
close_count += 1;
|
|
if open_count == close_count {
|
|
return res;
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
res += &c.to_string();
|
|
}
|
|
|
|
panic!(
|
|
"Encountered unablanced parentheses {} vs. {}",
|
|
open_count, close_count
|
|
);
|
|
}
|
|
|
|
fn extract_number(input: &str) -> String {
|
|
input.chars().take_while(|c| c.is_ascii_digit()).collect()
|
|
}
|
|
|
|
fn eval_expression(input: &str) -> u64 {
|
|
let mut clean: String = input.chars().filter(|c| *c != ' ').collect();
|
|
let mut res = 0;
|
|
let mut op = '^';
|
|
|
|
while clean != "" {
|
|
let c = clean.chars().nth(0).unwrap();
|
|
if c.is_ascii_digit() {
|
|
let substr = extract_number(&clean);
|
|
clean = clean[substr.len()..].to_string();
|
|
let num: u64 = substr.parse().unwrap();
|
|
match op {
|
|
'^' => res = num,
|
|
'+' => res += num,
|
|
'*' => res *= num,
|
|
_ => panic!("Unsupported Op: {}", op),
|
|
}
|
|
} else if c == '+' || c == '*' {
|
|
op = c;
|
|
clean = clean[1..].to_string();
|
|
} else if c == '(' {
|
|
let substr = extract_paren_expression(&clean);
|
|
clean = clean[substr.len() + 2..].to_string();
|
|
let num = eval_expression(&substr);
|
|
match op {
|
|
'^' => res = num,
|
|
'+' => res += num,
|
|
'*' => res *= num,
|
|
_ => panic!("Unsupported Op: {}", op),
|
|
}
|
|
}
|
|
}
|
|
|
|
res
|
|
}
|
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
|
let file = File::open("inputs/day18.txt")?;
|
|
let lines = io::BufReader::new(file).lines().map(|l| l.unwrap());
|
|
|
|
let res = lines.map(|l| eval_expression(&l)).fold(0, |x, y| x + y);
|
|
println!("Answer: {}", res);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::*;
|
|
|
|
#[test]
|
|
fn test_extractor() {
|
|
assert_eq!(
|
|
extract_paren_expression("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"),
|
|
"(2 + 4 * 9) * (6 + 9 * 8 + 6) + 6"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_basics() {
|
|
assert_eq!(eval_expression("23"), 23);
|
|
assert_eq!(eval_expression("2 + 3 * 4"), 20);
|
|
assert_eq!(eval_expression("2 + (3 * 4)"), 14);
|
|
}
|
|
|
|
#[test]
|
|
fn test_problems() {
|
|
assert_eq!(eval_expression("2 * 3 + (4 * 5)"), 26);
|
|
assert_eq!(eval_expression("5 + (8 * 3 + 9 + 3 * 4 * 3)"), 437);
|
|
assert_eq!(
|
|
eval_expression("5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))"),
|
|
12240
|
|
);
|
|
assert_eq!(
|
|
eval_expression("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"),
|
|
13632
|
|
);
|
|
}
|
|
}
|