Skip to content

Commit 7c4dbe4

Browse files
committed
[2024/6] p2 solved (slow - takes 5m30s)
1 parent 84ffacf commit 7c4dbe4

File tree

3 files changed

+75
-10
lines changed

3 files changed

+75
-10
lines changed

.aoc_tiles/tiles/2024/06.png

138 Bytes
Loading

2024/6/script.py

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,93 @@ def move(pos: tuple, dir_: Dir, grid: Grid) -> tuple[tuple, Dir]:
77
next_pos = pos + Vec2(dir_)
88

99
# out of bounds or open, return next position
10-
if not grid.in_bounds(next_pos) or not grid[next_pos] == '#':
10+
if not grid.in_bounds(next_pos) or not grid[next_pos] in '#O':
1111
return next_pos.as_tuple(), dir_
1212

1313
# obstacle, rotate right 90 degrees
1414
else:
1515
return pos, dir_.turn_right()
1616

1717

18-
def main():
19-
grid = Grid(aoc.read_lines())
20-
21-
pos = grid.find('^')
22-
dir_ = Dir.UP
23-
18+
def simulate(pos: tuple, dir_: Dir, grid: Grid) -> tuple[set, list, bool]:
2419
visited = set()
2520
visited.add(pos)
21+
path = []
22+
path.append((pos, dir_))
23+
loops = False
24+
2625
while grid.in_bounds(pos):
2726
pos, dir_ = move(pos, dir_, grid)
2827
visited.add(pos)
28+
if path[-1][0] == pos:
29+
path.append((pos, dir_))
30+
path.append((pos, None))
31+
elif (pos, dir_) in path:
32+
loops = True
33+
break
34+
else:
35+
path.append((pos, dir_))
36+
37+
return visited, path, loops
38+
39+
40+
def print_path(grid: Grid, path: list, start_pos: tuple):
41+
dir_chars = {
42+
Dir.UP: '|',
43+
Dir.DOWN: '|',
44+
Dir.LEFT: '-',
45+
Dir.RIGHT: '-',
46+
None: '+',
47+
}
48+
print(grid.render_with_overlays([{pos: dir_chars[dir_] for pos, dir_ in path},
49+
{start_pos: '^'}]))
50+
51+
52+
def main():
53+
grid = Grid(aoc.read_lines())
54+
55+
start_pos = grid.find('^')
56+
dir_ = Dir.UP
57+
58+
visited, path, _ = simulate(start_pos, dir_, grid)
59+
60+
# print(grid.render_with_overlays([{pos: 'X' for pos in visited}]))
61+
# print("p1:", len(visited) - 1)
62+
63+
# print_path(grid, path, start_pos)
64+
65+
loop_obstacles = set()
66+
tried_obstacles = set()
67+
path = [p for p in path if p[1] is not None]
68+
69+
# try placing an obstacle at every position along our initial path
70+
for i, pair in enumerate(path):
71+
pos = pair[0]
72+
73+
# skip the start position, out-of-bounds, and previously tried obstacles
74+
if pos == start_pos or not grid.in_bounds(pos) or pos in tried_obstacles:
75+
continue
76+
77+
# place the obstacle
78+
grid[pos] = 'O'
79+
tried_obstacles.add(pos)
80+
81+
# start pathing from just before the newly placed obstacle
82+
new_start_pos, new_dir = path[i-1] if path[i-1][0] != pos else path[i-2]
83+
84+
new_visited, new_path, loops = simulate(new_start_pos, new_dir, grid)
85+
86+
# track obstacles that cause loops
87+
if loops:
88+
loop_obstacles.add(pos)
89+
# print_path(grid, new_path, new_start_pos)
90+
print(f"{i}/{len(path)} {len(loop_obstacles)}")
91+
92+
# remove the current obstacle so we can try the next one
93+
grid[pos] = '.'
2994

30-
print(grid.render_with_overlays([{pos: 'X' for pos in visited}]))
3195
print("p1:", len(visited) - 1)
96+
print("p2:", len(loop_obstacles))
3297

3398

3499
if __name__ == "__main__":

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ My solutions to the yearly Advents of Code
33

44
<!-- AOC TILES BEGIN -->
55
<h1 align="center">
6-
Advent of Code - 172/462 ⭐
6+
Advent of Code - 173/462 ⭐
77
</h1>
88
<h1 align="center">
9-
2024 - 11 ⭐ - Python
9+
2024 - 12 ⭐ - Python
1010
</h1>
1111
<a href="2024/1/script.py">
1212
<img src=".aoc_tiles/tiles/2024/01.png" width="161px">

0 commit comments

Comments
 (0)