From 5900b4d3c63e80f1158bc485e55c71c8ea5901cc Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Wed, 23 Dec 2020 19:01:20 -0800 Subject: [PATCH] Day 18 part 2 BROKEN. --- 2020/src/day18.rs | 121 +++++++++++++++++++++++++++++++++++++++++----- 2020/src/lib.rs | 2 +- 2 files changed, 111 insertions(+), 12 deletions(-) diff --git a/2020/src/day18.rs b/2020/src/day18.rs index 6de82be..e650436 100644 --- a/2020/src/day18.rs +++ b/2020/src/day18.rs @@ -31,6 +31,27 @@ //! ((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2 becomes 13632. //! Before you can help with the homework, you need to understand it yourself. Evaluate the expression on each line of the homework; what is the sum of the resulting values? +//! --- Part Two --- +//! You manage to answer the child's questions and they finish part 1 of their homework, but get stuck when they reach the next section: advanced math. +//! +//! Now, addition and multiplication have different precedence levels, but they're not the ones you're familiar with. Instead, addition is evaluated before multiplication. +//! +//! For example, the steps to evaluate the expression 1 + 2 * 3 + 4 * 5 + 6 are now as follows: +//! +//! 1 + 2 * 3 + 4 * 5 + 6 +//! 3 * 3 + 4 * 5 + 6 +//! 3 * 7 * 5 + 6 +//! 3 * 7 * 11 +//! 21 * 11 +//! 231 +//! Here are the other examples from above: +//! +//! 1 + (2 * 3) + (4 * (5 + 6)) still becomes 51. +//! 2 * 3 + (4 * 5) becomes 46. +//! 5 + (8 * 3 + 9 + 3 * 4 * 3) becomes 1445. +//! 5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4)) becomes 669060. +//! ((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2 becomes 23340. +//! What do you get if you add up the results of evaluating the homework problems using these new rules? use aoc_runner_derive::{aoc, aoc_generator}; #[derive(Clone, Copy, Debug, PartialEq)] @@ -72,6 +93,80 @@ fn parse_part1(tokens: &[Token]) -> u64 { tokens.into_iter().for_each(|t| p.add_token(t)); p.eval() */ + let mut stack = vec![Vec::new()]; + let mut cur_stack = 0; + // Reverse the token list so we can pop them. + let mut tokens: Vec<_> = tokens.into_iter().rev().collect(); + while let Some(t) = tokens.pop() { + let mut peek = || { + let t = tokens.pop().unwrap(); + tokens.push(t); + t + }; + match t { + Token::Num(n) => { + let t2 = peek(); + if let Token::Add = t2 { + stack.push(vec![]); + cur_stack += 1; + } + match stack[cur_stack].last() { + Some(Token::Add) => { + stack[cur_stack].pop(); + if let Some(Token::Num(left)) = stack[cur_stack].pop() { + stack[cur_stack].push(Token::Num(left + n)); + } + } + Some(Token::Mul) => { + stack[cur_stack].pop(); + if let Some(Token::Num(left)) = stack[cur_stack].pop() { + stack[cur_stack].push(Token::Num(left * n)); + } + } + None => stack[cur_stack].push(*t), + c => { + dbg!(&c); + } + } + } + Token::Add => stack[cur_stack].push(*t), + Token::Mul => stack[cur_stack].push(*t), + Token::Open => { + stack.push(vec![]); + cur_stack += 1; + } + Token::Close => { + // Take the result of this parenthetical group and push it on to the stack one + // level below. + assert_eq!(stack[cur_stack].len(), 1); + let t = stack[cur_stack].pop().unwrap(); + stack.pop(); + cur_stack -= 1; + stack[cur_stack].push(t); + // If the stack has 3 things, it was waiting for this result. + let len = stack[cur_stack].len(); + if len >= 3 { + let s = &mut stack[cur_stack]; + match (s.pop(), s.pop(), s.pop()) { + (Some(Token::Num(right)), Some(op), Some(Token::Num(left))) => match op { + Token::Add => stack[cur_stack].push(Token::Num(left + right)), + Token::Mul => stack[cur_stack].push(Token::Num(left * right)), + d => panic!(format!("unexpected op {:?}", d)), + }, + d => panic!(format!("unexpected trio from on stack: {:?}", d)), + } + } + } + Token::Space => unreachable!("no space should be present"), + }; + } + match stack[cur_stack].last() { + Some(Token::Num(n)) => *n, + d => panic!(format!("Unexpected stack contents: {:?}", d)), + } +} + +fn parse_part2(tokens: &[Token]) -> u64 { let mut stack = vec![Vec::new()]; let mut cur_stack = 0; tokens.iter().for_each(|t| { @@ -131,16 +226,12 @@ fn parse_part1(tokens: &[Token]) -> u64 { } } -fn parse_part2(tokens: &[Token]) -> u64 { - todo!("parse_part2"); -} - #[aoc(day18, part1)] fn solution1(tokens_list: &[Vec]) -> u64 { tokens_list.iter().map(|tokens| parse_part1(tokens)).sum() } -//#[aoc(day18, part2)] +#[aoc(day18, part2)] fn solution2(tokens_list: &[Vec]) -> u64 { tokens_list.iter().map(|tokens| parse_part2(tokens)).sum() } @@ -167,7 +258,6 @@ mod tests { #[test] fn part1() { - // 1106240272 too low for (input, want) in vec![ ("1 + 2 * 3", 9), ("(1 + 2) * 3", 9), @@ -180,10 +270,8 @@ mod tests { ("5 + (8 * 3 + 9 + 3 * 4 * 3)", 437), ("5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))", 12240), ("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2", 13632), - //("((9 * 7 + 6 + 7 * 9 + 2) * 4 + 3 + 4 + 4 * 6) * 8 + (4 + (8 + 2 * 6 * 4 * 3)) + (5 + 2 * 6 * (4 * 5 + 4 + 2)) + 4 * (6 + 3 * (2 * 2 * 6 * 3) + 8 + 4 * 5)", 1740572064000), ] { let got = parse_part1(&lex(input)); - eprintln!("got {}, want {} for {}", got, want, input); assert_eq!(got, want, "got {}, want {} for {}", got, want, input); } let input = r#"1 + 2 * 3 + 4 * 5 + 6 @@ -194,6 +282,19 @@ mod tests { assert_eq!(solution1(&generator(input)), 71 + 26 + 437 + 12240 + 13632); } #[test] + fn part2() { + for (input, want) in vec![ + ("1 + (2 * 3) + (4 * (5 + 6))", 51), + ("2 * 3 + (4 * 5)", 46), + ("5 + (8 * 3 + 9 + 3 * 4 * 3)", 1445), + ("5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))", 669060), + ("((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2)", 23340), + ] { + let got = parse_part2(&lex(input)); + assert_eq!(got, want, "got {}, want {} for {}", got, want, input); + } + } + #[test] fn comprehensive_part1() { let mut ts = vec![ ("(7 * (3 + 8 + 8 + 7) + (6 + 8 * 2 + 5 + 2 * 6) * (5 + 2) * 9) + ((7 * 4 + 8) * 6 * 8 + 9) * 7 * 2 * 2", 740124), @@ -573,12 +674,11 @@ mod tests { ts.sort_by(|l, r| l.0.len().cmp(&r.0.len())); for (input, want) in ts { let got = parse_part1(&lex(input)); - eprintln!("got {}, want {} for {}", got, want, input); assert_eq!(got, want, "got {}, want {} for {}", got, want, input); } } - //#[test] + #[test] fn comprehensive_part2() { let mut ts = vec![ ("(7 * (3 + 8 + 8 + 7) + (6 + 8 * 2 + 5 + 2 * 6) * (5 + 2) * 9) + ((7 * 4 + 8) * 6 * 8 + 9) * 7 * 2 * 2", 9896040), @@ -958,7 +1058,6 @@ mod tests { ts.sort_by(|l, r| l.0.len().cmp(&r.0.len())); for (input, want) in ts { let got = parse_part2(&lex(input)); - eprintln!("got {}, want {} for {}", got, want, input); assert_eq!(got, want, "got {}, want {} for {}", got, want, input); } } diff --git a/2020/src/lib.rs b/2020/src/lib.rs index 6d721d2..39b1f16 100644 --- a/2020/src/lib.rs +++ b/2020/src/lib.rs @@ -7,7 +7,7 @@ pub mod day14; pub mod day15; pub mod day16; pub mod day17; -pub mod day18; +//pub mod day18; pub mod day19; pub mod day2; //pub mod day20;