From 7ec783fc16f3e346fef82ae59d08035a45cb9e6e Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Fri, 10 Dec 2021 14:26:31 +0100 Subject: [PATCH] 2021: day10: part 2 --- aoc2021/src/day10.rs | 66 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/aoc2021/src/day10.rs b/aoc2021/src/day10.rs index 49d35de..8ccacfb 100644 --- a/aoc2021/src/day10.rs +++ b/aoc2021/src/day10.rs @@ -8,6 +8,7 @@ pub fn run() -> Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -18,7 +19,21 @@ fn part1(input: &str) -> Result { .map(str::parse::) .collect::>>()?; - Ok(lines.iter().map(Line::corrupt_score).sum()) + Ok(lines.iter().filter_map(Line::syntax_checking_score).sum()) +} + +fn part2(input: &str) -> Result { + let lines = input + .lines() + .map(str::parse::) + .collect::>>()?; + + let mut scores: Vec = lines.iter().filter_map(Line::completion_score).collect(); + scores.sort_unstable(); + + debug_assert!(scores.len() % 2 == 1); + + Ok(scores[scores.len() / 2]) } enum SymbolState { @@ -47,7 +62,7 @@ enum Symbol { } impl Symbol { - fn score(&self) -> u64 { + fn syntax_checking_score(&self) -> u64 { match self { Symbol::Parenthesis => 3, Symbol::Bracket => 57, @@ -55,6 +70,15 @@ impl Symbol { Symbol::AngleBracket => 25137, } } + + fn completion_score(&self) -> u64 { + match self { + Symbol::Parenthesis => 1, + Symbol::Bracket => 2, + Symbol::Brace => 3, + Symbol::AngleBracket => 4, + } + } } impl TryFrom for Symbol { @@ -76,7 +100,7 @@ struct Line { } impl Line { - fn corrupt_score(&self) -> u64 { + fn syntax_checking_score(&self) -> Option { let mut stack = Vec::new(); for state in &self.symbols { @@ -84,12 +108,34 @@ impl Line { SymbolState::Open(symbol) => stack.push(symbol), SymbolState::Close(symbol) => match stack.pop() { Some(other_symbol) if symbol == other_symbol => continue, - _ => return symbol.score(), + _ => return Some(symbol.syntax_checking_score()), }, } } - 0 + None + } + + fn completion_score(&self) -> Option { + let mut stack = Vec::new(); + + for state in &self.symbols { + match state { + SymbolState::Open(symbol) => stack.push(symbol), + SymbolState::Close(symbol) => match stack.pop() { + Some(other_symbol) if symbol == other_symbol => continue, + _ => return None, // ignore corrupt line + }, + } + } + + let mut score = 0; + + for symbol in stack.into_iter().rev() { + score = score * 5 + symbol.completion_score(); + } + + Some(score) } } @@ -122,4 +168,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 394647); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 288957); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 2380061249); + } }