AoC2020/src/bin/day18.rs

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
);
}
}