1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
use std::collections::VecDeque;
use std::collections::HashMap;
fn main() {
let input = advent::read_lines(10);
println!("10a: {}", syntax_error_score(&input));
println!("10b: {}", completion_error_score(&input));
}
enum ParsingError {
Corrupt { illegal: char },
Incomplete { missing: VecDeque<char> },
}
fn parse_line(line: &str) -> Result<(), ParsingError> {
let mut openings = VecDeque::new();
let chunks = HashMap::from([
('(', ')'),
('[', ']'),
('{', '}'),
('<', '>'),
]);
for c in line.chars() {
if chunks.contains_key(&c) {
openings.push_front(c);
} else {
if openings.is_empty() {
return Err(ParsingError::Corrupt { illegal: c });
}
let expected = *chunks.get(openings.front().unwrap()).unwrap();
if expected != c {
return Err(ParsingError::Corrupt { illegal: c });
} else {
openings.pop_front();
}
}
}
if !openings.is_empty() {
Err(ParsingError::Incomplete { missing: openings })
} else {
Ok(())
}
}
fn syntax_error_score<T: AsRef<str>>(input: &[T]) -> usize {
let scores_corrupt = HashMap::from([
(')', 3),
(']', 57),
('}', 1197),
('>', 25137),
]);
let mut score = 0;
for line in input {
if let Err(ParsingError::Corrupt { illegal }) = parse_line(line.as_ref()) {
score += scores_corrupt.get(&illegal).unwrap();
}
}
score
}
fn completion_error_score<T: AsRef<str>>(input: &[T]) -> usize {
let scores_incomplete = HashMap::from([
('(', 1),
('[', 2),
('{', 3),
('<', 4),
]);
let mut scores = Vec::new();
for line in input {
if let Err(ParsingError::Incomplete { missing }) = parse_line(line.as_ref()) {
let mut score = 0;
for c in missing {
score *= 5;
score += scores_incomplete.get(&c).unwrap();
}
scores.push(score);
}
}
scores.sort_unstable();
scores[scores.len()/2]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
let input = [
"[({(<(())[]>[[{[]{<()<>>",
"[(()[<>])]({[<{<<[]>>(",
"{([(<{}[<>[]}>{[]{[(<()>",
"(((({<>}<{<{<>}{[]{[]{}",
"[[<[([]))<([[{}[[()]]]",
"[{[{({}]{}}([{[{{{}}([]",
"{<[[]]>}<{[{[{[]{()[[[]",
"[<(<(<(<{}))><([]([]()",
"<{([([[(<>()){}]>(<<{{",
"<{([{{}}[<[[[<>{}]]]>[]]",
];
assert_eq!(syntax_error_score(&input), 26397);
assert_eq!(completion_error_score(&input), 288957);
}
}
|