2021: day10: part 2

This commit is contained in:
Antoine Martin 2021-12-10 14:26:31 +01:00
parent 6c7b3d9cc6
commit 7ec783fc16

View file

@ -8,6 +8,7 @@ pub fn run() -> Result<String> {
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<u64> {
.map(str::parse::<Line>)
.collect::<Result<Vec<_>>>()?;
Ok(lines.iter().map(Line::corrupt_score).sum())
Ok(lines.iter().filter_map(Line::syntax_checking_score).sum())
}
fn part2(input: &str) -> Result<u64> {
let lines = input
.lines()
.map(str::parse::<Line>)
.collect::<Result<Vec<_>>>()?;
let mut scores: Vec<u64> = 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<char> for Symbol {
@ -76,7 +100,7 @@ struct Line {
}
impl Line {
fn corrupt_score(&self) -> u64 {
fn syntax_checking_score(&self) -> Option<u64> {
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<u64> {
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);
}
}