Skip to content

Commit 9b9bd69

Browse files
committed
Faster approach with incremental BFS
1 parent 15739f5 commit 9b9bd69

File tree

2 files changed

+48
-36
lines changed

2 files changed

+48
-36
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ Performance is reasonable even on older hardware, for example a 2011 MacBook Pro
8989
| 15 | [Warehouse Woes](https://adventofcode.com/2024/day/15) | [Source](src/year2024/day15.rs) | 303 |
9090
| 16 | [Reindeer Maze](https://adventofcode.com/2024/day/16) | [Source](src/year2024/day16.rs) | 390 |
9191
| 17 | [Chronospatial Computer](https://adventofcode.com/2024/day/17) | [Source](src/year2024/day17.rs) | 2 |
92-
| 18 | [RAM Run](https://adventofcode.com/2024/day/18) | [Source](src/year2024/day18.rs) | 61 |
92+
| 18 | [RAM Run](https://adventofcode.com/2024/day/18) | [Source](src/year2024/day18.rs) | 42 |
9393

9494
## 2023
9595

src/year2024/day18.rs

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,66 +14,78 @@
1414
//! ```
1515
//!
1616
//! Now we can [BFS](https://en.wikipedia.org/wiki/Breadth-first_search) from any arbitrary
17-
//! start time. Squares are blocked only if the grid time is less than or equal to the start time.
18-
//!
19-
//! A [binary search](https://en.wikipedia.org/wiki/Binary_search) is much faster than a
20-
//! linear search with complexity `O(log₂n)` vs `O(n)`. For example `log₂(3450) = 12`.
17+
//! start time. Squares are allowed if the grid time is greater than the start time.
2118
use crate::util::grid::*;
2219
use crate::util::iter::*;
2320
use crate::util::parse::*;
2421
use crate::util::point::*;
22+
use crate::util::heap::*;
2523
use std::collections::VecDeque;
2624

27-
pub fn parse(input: &str) -> Grid<u16> {
28-
let mut grid = Grid::new(71, 71, u16::MAX);
25+
pub fn parse(input: &str) -> Grid<i32> {
26+
let mut grid = Grid::new(71, 71, i32::MAX);
2927

3028
for (i, [x, y]) in input.iter_signed::<i32>().chunk::<2>().enumerate() {
31-
grid[Point::new(x, y)] = i as u16;
29+
grid[Point::new(x, y)] = i as i32;
3230
}
3331

3432
grid
3533
}
3634

37-
pub fn part1(grid: &Grid<u16>) -> u32 {
38-
bfs(grid, 1024).unwrap()
39-
}
40-
41-
pub fn part2(grid: &Grid<u16>) -> String {
42-
let mut lower = 0;
43-
let mut upper = 5041;
44-
45-
while lower < upper {
46-
let middle = (lower + upper) / 2;
47-
if bfs(grid, middle).is_some() {
48-
lower = middle + 1;
49-
} else {
50-
upper = middle;
51-
}
52-
}
53-
54-
let index = grid.bytes.iter().position(|&time| time == lower).unwrap() as i32;
55-
format!("{},{}", index % grid.width, index / grid.width)
56-
}
57-
58-
fn bfs(grid: &Grid<u16>, time: u16) -> Option<u32> {
35+
pub fn part1(grid: &Grid<i32>) -> u32 {
36+
let mut grid = grid.clone();
5937
let mut todo = VecDeque::new();
60-
let mut seen = grid.clone();
6138

39+
grid[ORIGIN] = 0;
6240
todo.push_back((ORIGIN, 0));
63-
seen[ORIGIN] = 0;
6441

6542
while let Some((position, cost)) = todo.pop_front() {
6643
if position == Point::new(70, 70) {
67-
return Some(cost);
44+
return cost;
6845
}
6946

7047
for next in ORTHOGONAL.map(|o| position + o) {
71-
if seen.contains(next) && time < seen[next] {
48+
if grid.contains(next) && grid[next] > 1024 {
49+
grid[next] = 0;
7250
todo.push_back((next, cost + 1));
73-
seen[next] = 0;
7451
}
7552
}
7653
}
7754

78-
None
55+
unreachable!()
56+
}
57+
58+
pub fn part2(grid: &Grid<i32>) -> String {
59+
let mut time = i32::MAX;
60+
let mut heap = MinHeap::new();
61+
62+
let mut grid = grid.clone();
63+
let mut todo = VecDeque::new();
64+
65+
grid[ORIGIN] = 0;
66+
todo.push_back(ORIGIN);
67+
68+
loop {
69+
while let Some(position) = todo.pop_front() {
70+
if position == Point::new(70, 70) {
71+
let index = grid.bytes.iter().position(|&b| b == time).unwrap() as i32;
72+
return format!("{},{}", index % grid.width, index / grid.width);
73+
}
74+
75+
for next in ORTHOGONAL.map(|o| position + o) {
76+
if grid.contains(next) {
77+
if time < grid[next] {
78+
grid[next] = 0;
79+
todo.push_back(next);
80+
} else {
81+
heap.push(-grid[next], next);
82+
}
83+
}
84+
}
85+
}
86+
87+
let (first, saved) = heap.pop().unwrap();
88+
time = -first;
89+
todo.push_back(saved);
90+
}
7991
}

0 commit comments

Comments
 (0)