108 lines
2.6 KiB
Rust
108 lines
2.6 KiB
Rust
#![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);
|