Untitled
unknown
plain_text
a year ago
3.0 kB
79
Indexable
pub fn solution(test: bool) -> ((usize, Duration), (usize, Duration)) {
let lines;
if test {
lines = include_str!("../../../AdventOfCodeInputs/problem_inputs_2024/day_18_test.txt");
} else {
lines = include_str!("../../../AdventOfCodeInputs/problem_inputs_2024/day_18.txt");
}
(solve01(lines), solve02(lines))
}
fn solve01(lines: &str) -> (usize, Duration) {
let now = Instant::now();
let maze = Maze::from_str(lines, (71, 71), 1024);
let start = (0, 0);
let end = (maze.bounds.0 - 1, maze.bounds.1 - 1);
let result = maze.find_shortest_path(start, end).unwrap();
(result, now.elapsed())
}
fn solve02(lines: &str) -> (usize, Duration) {
let now = Instant::now();
let mut low = 1024;
let mut high = lines.lines().count();
let mut result = 0;
while low <= high {
let mid = (low + high) / 2;
let maze = Maze::from_str(lines, (71, 71), mid);
let start = (0, 0);
let end = (maze.bounds.0 - 1, maze.bounds.1 - 1);
if maze.find_shortest_path(start, end).is_some() {
result = mid;
low = mid + 1;
} else {
high = mid - 1;
}
}
dbg!(lines.lines().nth(result));
(0, now.elapsed())
}
type Pos = (isize, isize);
struct Maze {
blocks: FxHashSet<Pos>,
bounds: (isize, isize),
}
impl Maze {
fn from_str(lines: &str, bounds: (isize, isize), bytes_to_count: usize) -> Self {
let mut blocks = FxHashSet::default();
for pos in lines.lines().take(bytes_to_count) {
let (xstr, ystr) = pos.split_once(',').unwrap();
let x = xstr.parse::<isize>().unwrap();
let y = ystr.parse::<isize>().unwrap();
blocks.insert((x, y));
}
Self { blocks, bounds }
}
fn find_shortest_path(&self, start: Pos, end: Pos) -> Option<usize> {
let mut dist = FxHashSet::default();
let mut heap = VecDeque::new();
heap.push_back((0, start));
while let Some((cost, pos)) = heap.pop_front() {
if pos == end {
return Some(cost);
}
if !dist.insert(pos) {
continue;
}
for neighbour in self.get_neighbours(pos) {
if !dist.contains(&neighbour) {
heap.push_back((cost + 1, neighbour));
}
}
}
None
}
fn get_neighbours(&self, pos: Pos) -> Vec<Pos> {
let mut neighbours = Vec::new();
let (x, y) = pos;
for (dx, dy) in &[(0, 1), (0, -1), (1, 0), (-1, 0)] {
let next = (x + dx, y + dy);
if next.0 < 0 || next.1 < 0 || next.0 >= self.bounds.0 || next.1 >= self.bounds.1 {
continue;
}
if self.blocks.contains(&next) {
continue;
}
neighbours.push(next);
}
neighbours
}
}Editor is loading...
Leave a Comment