Skip to content

Commit 0a4f815

Browse files
committed
day 16 part two
1 parent 186ac64 commit 0a4f815

File tree

2 files changed

+100
-14
lines changed

2 files changed

+100
-14
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,8 @@ Part Two: 3687727854171
6262
--- Day 15: Rambunctious Recitation ---
6363
Part One: 1111
6464
Part Two: 48568
65+
66+
--- Day 16: Ticket Translation ---
67+
Part One: 25916
68+
Part Two: 2564529489989
6569
```

src/day16.rs

Lines changed: 96 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
fn parse_input(
2-
input: &str,
3-
) -> (Vec<(&str, Vec<(u32, u32)>)>, Vec<u32>, Vec<Vec<u32>>) {
1+
use std::cmp::Reverse;
2+
use std::collections::BinaryHeap;
3+
4+
type Ranges = Vec<(u64, u64)>;
5+
type Rule<'a> = (&'a str, Ranges);
6+
type Ticket = Vec<u64>;
7+
type Tickets = Vec<Ticket>;
8+
9+
fn parse_input(input: &str) -> (Vec<Rule>, Ticket, Tickets) {
410
let sections: Vec<&str> =
511
input.trim().split("\n\n").collect::<Vec<&str>>();
6-
let rules: Vec<(&str, Vec<(u32, u32)>)> = sections[0]
12+
let rules: Vec<Rule> = sections[0]
713
.trim()
814
.lines()
915
.map(|s| {
@@ -21,16 +27,15 @@ fn parse_input(
2127
})
2228
.collect();
2329

24-
let ticket: Vec<u32> = sections[1]
30+
let ticket: Vec<u64> = sections[1]
2531
.lines()
26-
.skip(1)
27-
.next()
32+
.nth(1)
2833
.unwrap()
2934
.split(',')
3035
.map(|s| s.parse().unwrap())
3136
.collect();
3237

33-
let nearby_tickets: Vec<Vec<u32>> = sections[2]
38+
let nearby_tickets: Vec<Vec<u64>> = sections[2]
3439
.lines()
3540
.skip(1)
3641
.map(|s| s.split(',').map(|s| s.parse().unwrap()).collect())
@@ -39,23 +44,86 @@ fn parse_input(
3944
(rules, ticket, nearby_tickets)
4045
}
4146

42-
pub fn part_one(input: &str) -> u32 {
47+
pub fn part_one(input: &str) -> u64 {
4348
let (rules, _, nearby_tickets) = parse_input(input);
44-
45-
let is_invalid = |value: u32| -> bool {
49+
let is_invalid = |value: u64| -> bool {
4650
rules.iter().all(|(_, ranges)| {
4751
ranges.iter().all(|&(min, max)| value < min || value > max)
4852
})
4953
};
50-
5154
nearby_tickets
5255
.iter()
5356
.flat_map(|ticket| ticket.iter().filter(|&value| is_invalid(*value)))
5457
.sum()
5558
}
5659

57-
pub fn part_two(input: &str) -> usize {
58-
0
60+
fn determined_ticket_fields(input: &str) -> Vec<(&str, u64)> {
61+
let (rules, ticket, nearby_tickets) = parse_input(input);
62+
63+
let tickets: Vec<Vec<u64>> = nearby_tickets
64+
.into_iter()
65+
.filter(|ticket| {
66+
ticket.iter().all(|&value| {
67+
rules.iter().any(|(_, ranges)| {
68+
ranges
69+
.iter()
70+
.any(|&(min, max)| value >= min && value <= max)
71+
})
72+
})
73+
})
74+
.collect();
75+
76+
let valids: Vec<Vec<Vec<bool>>> = tickets
77+
.iter()
78+
.map(|ticket| {
79+
ticket
80+
.iter()
81+
.map(|value| {
82+
rules
83+
.iter()
84+
.map(|(_, ranges)| {
85+
ranges.iter().any(|&(min, max)| {
86+
*value >= min && *value <= max
87+
})
88+
})
89+
.collect()
90+
})
91+
.collect()
92+
})
93+
.collect();
94+
95+
let h = valids.len();
96+
let w = valids[0].len();
97+
let valid_fields: Vec<Vec<usize>> = (0..w)
98+
.map(|x| {
99+
(0..rules.len())
100+
.filter(|i| (0..h).all(|y| valids[y][x][*i]))
101+
.collect()
102+
})
103+
.collect();
104+
105+
let mut queue = BinaryHeap::new();
106+
let mut visited = vec![false; valid_fields.len()];
107+
108+
for (i, fields) in valid_fields.iter().enumerate() {
109+
queue.push(Reverse((fields.len(), i, fields)));
110+
}
111+
112+
let mut ticket_fields = Vec::new();
113+
while let Some(Reverse((_, i, fields))) = queue.pop() {
114+
let v = fields.iter().find(|&&v| !visited[v]).unwrap();
115+
visited[*v] = true;
116+
ticket_fields.push((rules[*v].0, ticket[i]));
117+
}
118+
ticket_fields
119+
}
120+
121+
pub fn part_two(input: &str) -> u64 {
122+
determined_ticket_fields(input)
123+
.iter()
124+
.filter(|(s, _)| s.starts_with("departure"))
125+
.map(|(_, v)| *v)
126+
.product()
59127
}
60128

61129
#[cfg(test)]
@@ -85,4 +153,18 @@ fn example_part_two() {
85153
"15,1,5\n",
86154
"5,14,9"
87155
);
156+
157+
let fields = determined_ticket_fields(&input);
158+
assert!(fields
159+
.iter()
160+
.find(|(n, v)| n == &"class" && v == &12)
161+
.is_some());
162+
assert!(fields
163+
.iter()
164+
.find(|(n, v)| n == &"row" && v == &11)
165+
.is_some());
166+
assert!(fields
167+
.iter()
168+
.find(|(n, v)| n == &"seat" && v == &13)
169+
.is_some());
88170
}

0 commit comments

Comments
 (0)