-
Notifications
You must be signed in to change notification settings - Fork 3
/
day_13.rs
108 lines (91 loc) · 2.53 KB
/
day_13.rs
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::cmp::Ordering;
use common::{solution, Answer};
solution!("Distress Signal", 13);
fn part_a(input: &str) -> Answer {
let signals = parse(input);
signals
.chunks(2)
.enumerate()
.filter(|x| x.1[0].cmp(&x.1[1]) == Ordering::Less)
.map(|x| 1 + x.0)
.sum::<usize>()
.into()
}
fn part_b(input: &str) -> Answer {
let mut signals = parse(input);
let div = [Token::Number(6), Token::Number(2)];
signals.extend(div.clone());
signals.sort();
signals
.iter()
.enumerate()
.filter(|x| div.contains(x.1))
.map(|x| x.0 + 1)
.product::<usize>()
.into()
}
#[derive(Debug, Clone, PartialEq, Eq)]
enum Token {
Number(u32),
List(Vec<Token>),
}
fn parse(raw: &str) -> Vec<Token> {
raw.split("\n\n")
.flat_map(|x| {
x.lines()
.map(tokenisze)
.map(Token::List)
.collect::<Vec<_>>()
})
.collect()
}
impl Ord for Token {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(Token::Number(l), Token::Number(r)) => l.cmp(r),
(Token::List(l), Token::List(r)) => l.cmp(r),
(Token::Number(l), Token::List(r)) => vec![Token::Number(*l)].cmp(r),
(Token::List(l), Token::Number(r)) => l.cmp(&vec![Token::Number(*r)]),
}
}
}
impl PartialOrd for Token {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
fn tokenisze(raw: &str) -> Vec<Token> {
let mut out = Vec::new();
let mut working = String::new();
let mut in_list = 0;
for i in raw.chars().filter(|x| !x.is_ascii_whitespace()) {
match i {
'[' if in_list > 0 => in_list += 1,
']' if in_list > 0 => in_list -= 1,
_ => {}
}
match i {
'[' if in_list == 0 => in_list += 1,
']' if in_list == 1 => {
flush(&mut working, &mut out);
in_list -= 1;
}
_ if in_list > 0 => working.push(i),
',' => flush(&mut working, &mut out),
i if i.is_ascii_digit() => working.push(i),
_ => {}
}
}
flush(&mut working, &mut out);
out
}
fn flush(working: &mut String, out: &mut Vec<Token>) {
if working.is_empty() {
return;
}
match working.parse::<u32>() {
Ok(i) => out.push(Token::Number(i)),
Err(_) => out.push(Token::List(tokenisze(working))),
}
working.clear();
}