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