Skip to content

Commit 579d21c

Browse files
committed
Don't move robot
1 parent dfb46f9 commit 579d21c

File tree

2 files changed

+25
-40
lines changed

2 files changed

+25
-40
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ Performance is reasonable even on older hardware, for example a 2011 MacBook Pro
8686
| 12 | [Garden Groups](https://adventofcode.com/2024/day/12) | [Source](src/year2024/day12.rs) | 289 |
8787
| 13 | [Claw Contraption](https://adventofcode.com/2024/day/13) | [Source](src/year2024/day13.rs) | 14 |
8888
| 14 | [Restroom Redoubt](https://adventofcode.com/2024/day/14) | [Source](src/year2024/day14.rs) | 74 |
89-
| 15 | [Warehouse Woes](https://adventofcode.com/2024/day/15) | [Source](src/year2024/day15.rs) | 332 |
89+
| 15 | [Warehouse Woes](https://adventofcode.com/2024/day/15) | [Source](src/year2024/day15.rs) | 303 |
9090

9191
## 2023
9292

src/year2024/day15.rs

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ pub fn parse(input: &str) -> Input<'_> {
3535
pub fn part1(input: &Input<'_>) -> i32 {
3636
let (grid, moves) = input;
3737

38+
// We don't need to move the robot symbol so mark as empty space once located.
3839
let mut grid = grid.clone();
3940
let mut position = grid.find(b'@').unwrap();
41+
grid[position] = b'.';
4042

4143
// Treat moves as a single string ignoring any newline characters.
4244
for b in moves.bytes() {
@@ -57,18 +59,17 @@ pub fn part2(input: &Input<'_>) -> i32 {
5759

5860
let mut grid = stretch(grid);
5961
let mut position = grid.find(b'@').unwrap();
62+
grid[position] = b'.';
6063

6164
// Reuse to minimize allocations.
62-
let mut todo = Vec::new();
63-
let mut seen = grid.same_size_with(usize::MAX);
65+
let mut todo = Vec::with_capacity(50);
6466

65-
// Use index as a unique id for each move.
66-
for (id, b) in moves.bytes().enumerate() {
67+
for b in moves.bytes() {
6768
match b {
6869
b'<' => narrow(&mut grid, &mut position, LEFT),
6970
b'>' => narrow(&mut grid, &mut position, RIGHT),
70-
b'^' => wide(&mut grid, &mut position, UP, &mut todo, &mut seen, id),
71-
b'v' => wide(&mut grid, &mut position, DOWN, &mut todo, &mut seen, id),
71+
b'^' => wide(&mut grid, &mut position, UP, &mut todo),
72+
b'v' => wide(&mut grid, &mut position, DOWN, &mut todo),
7273
_ => (),
7374
}
7475
}
@@ -78,7 +79,7 @@ pub fn part2(input: &Input<'_>) -> i32 {
7879

7980
fn narrow(grid: &mut Grid<u8>, start: &mut Point, direction: Point) {
8081
let mut position = *start + direction;
81-
let mut size = 2;
82+
let mut size = 1;
8283

8384
// Search for the next wall or open space.
8485
while grid[position] != b'.' && grid[position] != b'#' {
@@ -89,7 +90,7 @@ fn narrow(grid: &mut Grid<u8>, start: &mut Point, direction: Point) {
8990
// Move items one space in direction.
9091
if grid[position] == b'.' {
9192
let mut previous = b'.';
92-
let mut position = *start;
93+
let mut position = *start + direction;
9394

9495
for _ in 0..size {
9596
swap(&mut previous, &mut grid[position]);
@@ -101,58 +102,42 @@ fn narrow(grid: &mut Grid<u8>, start: &mut Point, direction: Point) {
101102
}
102103
}
103104

104-
fn wide(
105-
grid: &mut Grid<u8>,
106-
start: &mut Point,
107-
direction: Point,
108-
todo: &mut Vec<Point>,
109-
seen: &mut Grid<usize>,
110-
id: usize,
111-
) {
105+
fn wide(grid: &mut Grid<u8>, start: &mut Point, direction: Point, todo: &mut Vec<Point>) {
112106
// Short circuit if path in front of robot is empty.
113-
let position = *start;
114-
let next = position + direction;
115-
116-
if grid[next] == b'.' {
117-
grid[position] = b'.';
118-
grid[next] = b'@';
107+
if grid[*start + direction] == b'.' {
119108
*start += direction;
120109
return;
121110
}
122111

123112
// Clear any items from previous push.
124113
todo.clear();
114+
// Add dummy item at the start to prevent index of out bounds when checking for previously
115+
// added boxes.
116+
todo.push(ORIGIN);
125117
todo.push(*start);
126-
let mut index = 0;
118+
let mut index = 1;
127119

128120
while index < todo.len() {
129121
let next = todo[index] + direction;
130122
index += 1;
131123

132-
let other = match grid[next] {
124+
// Add boxes strictly left to right.
125+
let (first, second) = match grid[next] {
126+
b'[' => (next, next + RIGHT),
127+
b']' => (next + LEFT, next),
133128
b'#' => return, // Return early if there's a wall in the way.
134-
b'[' => RIGHT,
135-
b']' => LEFT,
136-
_ => continue, // Open space doesn't add any more items to move.
129+
_ => continue, // Open space doesn't add any more items to move.
137130
};
138131

139-
// Enqueue the first half of box directly above us.
140-
let first = next;
141-
if seen[first] != id {
142-
seen[first] = id;
132+
// Check if this box has already been added by the previous box in this row.
133+
if first != todo[todo.len() - 2] {
143134
todo.push(first);
144-
}
145-
146-
// Enqueue the other half of the box directly above us.
147-
let second = next + other;
148-
if seen[second] != id {
149-
seen[second] = id;
150135
todo.push(second);
151136
}
152137
}
153138

154-
// Move boxes in reverse order.
155-
for &point in todo.iter().rev() {
139+
// Move boxes in reverse order (skipping the robot as an optimization).
140+
for &point in todo[2..].iter().rev() {
156141
grid[point + direction] = grid[point];
157142
grid[point] = b'.';
158143
}

0 commit comments

Comments
 (0)