2021: day10: part 2
This commit is contained in:
parent
6c7b3d9cc6
commit
7ec783fc16
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue