-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path20.rs
108 lines (91 loc) · 2.61 KB
/
20.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
#![feature(test)]
use std::collections::VecDeque;
use aoc::grid::Direction;
#[derive(Debug)]
struct Input {
end: (usize, usize),
grid: Vec<Vec<bool>>,
}
fn setup(input: &str) -> Input {
let mut end = None;
let grid = input
.trim()
.lines()
.enumerate()
.map(|(y, l)| {
l.bytes()
.enumerate()
.map(|(x, b)| match b {
b'.' => true,
b'#' => false,
b'S' => true,
b'E' => {
end = Some((x, y));
true
}
_ => panic!(),
})
.collect()
})
.collect();
Input {
end: end.unwrap(),
grid,
}
}
fn solve<const N: usize>(input: &Input) -> usize {
let n = N as isize;
let width = input.grid[0].len();
let height = input.grid.len();
let mut shortest = vec![usize::MAX; width * height];
let mut queue = VecDeque::from([(0, input.end)]);
let mut visited = vec![false; width * height];
while let Some((d, (x, y))) = queue.pop_front() {
let idx = y * width + x;
if std::mem::replace(&mut visited[idx], true) {
continue;
}
shortest[idx] = d;
queue.extend(
Direction::iter()
.flat_map(|d| d.step(x, y, width, height))
.filter(|&(nx, ny)| input.grid[ny][nx])
.map(|q| (d + 1, q)),
);
}
let mut out = 0;
for csy in 0..height {
for csx in 0..width {
if !input.grid[csy][csx] {
continue;
}
for dy in -n..=n {
let n = n - dy.abs();
for dx in -n..=n {
let cex = csx as isize + dx;
let cey = csy as isize + dy;
if !(0..width as isize).contains(&cex) || !(0..height as isize).contains(&cey) {
continue;
}
let cex = cex as usize;
let cey = cey as usize;
if !input.grid[cey][cex] {
continue;
}
let d = (dx.abs() + dy.abs()) as usize;
if shortest[cey * width + cex] + d + 100 <= shortest[csy * width + csx] {
out += 1;
}
}
}
}
}
out
}
fn part1(input: &Input) -> usize {
solve::<2>(input)
}
fn part2(input: &Input) -> usize {
solve::<20>(input)
}
aoc::main!(2024, 20);