Skip to content

Commit 8b44137

Browse files
committed
Don't move robot
1 parent dfb46f9 commit 8b44137

File tree

2 files changed

+25
-39
lines changed

2 files changed

+25
-39
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 & 38 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,18 @@ 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

6567
// Use index as a unique id for each move.
66-
for (id, b) in moves.bytes().enumerate() {
68+
for b in moves.bytes() {
6769
match b {
6870
b'<' => narrow(&mut grid, &mut position, LEFT),
6971
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),
72+
b'^' => wide(&mut grid, &mut position, UP, &mut todo),
73+
b'v' => wide(&mut grid, &mut position, DOWN, &mut todo),
7274
_ => (),
7375
}
7476
}
@@ -78,7 +80,7 @@ pub fn part2(input: &Input<'_>) -> i32 {
7880

7981
fn narrow(grid: &mut Grid<u8>, start: &mut Point, direction: Point) {
8082
let mut position = *start + direction;
81-
let mut size = 2;
83+
let mut size = 1;
8284

8385
// Search for the next wall or open space.
8486
while grid[position] != b'.' && grid[position] != b'#' {
@@ -89,7 +91,7 @@ fn narrow(grid: &mut Grid<u8>, start: &mut Point, direction: Point) {
8991
// Move items one space in direction.
9092
if grid[position] == b'.' {
9193
let mut previous = b'.';
92-
let mut position = *start;
94+
let mut position = *start + direction;
9395

9496
for _ in 0..size {
9597
swap(&mut previous, &mut grid[position]);
@@ -101,58 +103,42 @@ fn narrow(grid: &mut Grid<u8>, start: &mut Point, direction: Point) {
101103
}
102104
}
103105

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-
) {
106+
fn wide(grid: &mut Grid<u8>, start: &mut Point, direction: Point, todo: &mut Vec<Point>) {
112107
// 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'@';
108+
if grid[*start + direction] == b'.' {
119109
*start += direction;
120110
return;
121111
}
122112

123113
// Clear any items from previous push.
124114
todo.clear();
115+
// Add dummy item at the start to prevent index of out bounds when checking for previously
116+
// added boxes.
117+
todo.push(ORIGIN);
125118
todo.push(*start);
126-
let mut index = 0;
119+
let mut index = 1;
127120

128121
while index < todo.len() {
129122
let next = todo[index] + direction;
130123
index += 1;
131124

132-
let other = match grid[next] {
125+
// Add boxes strictly left to right.
126+
let (first, second) = match grid[next] {
127+
b'[' => (next, next + RIGHT),
128+
b']' => (next + LEFT, next),
133129
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.
130+
_ => continue, // Open space doesn't add any more items to move.
137131
};
138132

139-
// Enqueue the first half of box directly above us.
140-
let first = next;
141-
if seen[first] != id {
142-
seen[first] = id;
133+
// Check if this box has already been added by the previous box in this row.
134+
if first != todo[todo.len() - 2] {
143135
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;
150136
todo.push(second);
151137
}
152138
}
153139

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

0 commit comments

Comments
 (0)