Skip to content

Commit a65716a

Browse files
committed
[2024/15] p2 solved
1 parent a8d07c9 commit a65716a

File tree

4 files changed

+123
-24
lines changed

4 files changed

+123
-24
lines changed

.aoc_tiles/tiles/2024/15.png

48 Bytes
Loading

2024/15/example_p2

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#######
2+
#...#.#
3+
#.....#
4+
#..OO@#
5+
#..O..#
6+
#.....#
7+
#######
8+
9+
<vv<<^^<<^^

2024/15/script.py

Lines changed: 112 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
from GhostyUtils import aoc
22
from GhostyUtils.grid import Grid
33
from GhostyUtils.vec2 import Vec2, Dir
4+
from typing import Union
45

56

67
class Robot:
78
def __init__(self, pos: Vec2) -> 'Robot':
89
self.pos = Vec2(pos)
910

11+
def process(self, instructions: str, grid: Grid):
12+
for instr in instructions:
13+
if instr == '\n':
14+
continue
15+
self.move(Dir.map_nswe('^v<>')[instr], grid)
16+
17+
if aoc.args.verbose:
18+
print(instr)
19+
print(grid)
20+
1021
def move(self, dir: Dir, grid: Grid) -> bool:
1122
if grid[self.pos + dir].move(dir, grid):
1223
grid[self.pos] = Air(self.pos)
@@ -22,17 +33,60 @@ def __str__(self) -> str:
2233
class Box:
2334
def __init__(self, pos: Vec2) -> 'Box':
2435
self.pos = Vec2(pos)
36+
self.width = 1
37+
self.last_draw = -1
38+
39+
def touching(self, dir: Dir, grid: Grid) -> set[Union['Box', 'Wall', 'Air']]:
40+
if dir in {Dir.NORTH, Dir.SOUTH}:
41+
cells = filter(lambda c: type(c) is not Air,
42+
(grid[self.pos + Vec2(Dir.EAST) * i + dir]
43+
for i in range(self.width)))
44+
else:
45+
cells = filter(lambda c: type(c) is not Air,
46+
[grid[self.pos + (dir if dir == Dir.WEST else Vec2(dir) * self.width)]])
47+
cells = set(cells)
48+
49+
return cells
50+
51+
def can_move(self, dir: Dir, grid: Grid) -> bool:
52+
return all(cell.can_move(dir, grid) for cell in self.touching(dir, grid))
2553

2654
def move(self, dir: Dir, grid: Grid) -> bool:
27-
if grid[self.pos + dir].move(dir, grid):
28-
grid[self.pos] = Air(self.pos)
29-
self.pos += dir
30-
grid[self.pos] = self
31-
return True
32-
return False
55+
if not self.can_move(dir, grid):
56+
return False
57+
58+
for cell in self.touching(dir, grid):
59+
grid[cell.pos].move(dir, grid)
60+
61+
self.pos += dir
62+
if dir == Dir.WEST:
63+
grid[self.pos + Vec2(Dir.EAST) * self.width] = Air(None)
64+
for i in range(self.width):
65+
grid[self.pos + Vec2(Dir.EAST) * i] = self
66+
elif dir == Dir.EAST:
67+
grid[self.pos + Vec2(Dir.WEST)] = Air(None)
68+
for i in range(self.width):
69+
grid[self.pos + Vec2(Dir.EAST) * i] = self
70+
else:
71+
for i in range(self.width):
72+
grid[self.pos + Vec2(Dir.EAST) * i - dir] = Air(None)
73+
grid[self.pos + Vec2(Dir.EAST) * i] = self
74+
return True
75+
76+
def gps(self) -> int:
77+
return 100 * self.pos.y + self.pos.x
3378

3479
def __str__(self) -> str:
35-
return 'O'
80+
if self.width == 1:
81+
return 'O'
82+
elif self.width == 2:
83+
self.last_draw += 1
84+
if self.last_draw > 1:
85+
self.last_draw = 0
86+
return '[]'[self.last_draw]
87+
88+
def __repr__(self) -> str:
89+
return f"Box at {self.pos}"
3690

3791

3892
class Wall:
@@ -42,9 +96,15 @@ def __init__(self, pos: Vec2) -> 'Wall':
4296
def move(self, dir: Dir, grid: Grid) -> bool:
4397
return False
4498

99+
def can_move(self, dir: Dir, grid: Grid) -> bool:
100+
return False
101+
45102
def __str__(self) -> str:
46103
return '#'
47104

105+
def __repr__(self) -> str:
106+
return f"Wall at {self.pos}"
107+
48108

49109
class Air:
50110
def __init__(self, pos: Vec2) -> 'Air':
@@ -53,38 +113,68 @@ def __init__(self, pos: Vec2) -> 'Air':
53113
def move(self, dir: Dir, grid: Grid) -> bool:
54114
return True
55115

116+
def can_move(self, dir: Dir, grid: Grid) -> bool:
117+
return True
118+
56119
def __str__(self) -> str:
57120
return '.'
58121

59122

60-
def convert(cell: str, pos: Vec2) -> Robot | Box | Wall | Air:
61-
return {'@': Robot, '#': Wall, 'O': Box, '.': Air}[cell](pos)
62-
123+
def build_warehouse(floorplan: str, wide: bool = False) -> tuple[Grid, Robot, list[Box]]:
124+
floorplan = floorplan.splitlines()
125+
if wide:
126+
new_floorplan = []
127+
for row in floorplan:
128+
new_row = []
129+
for c in row:
130+
new_row.append({'#': '##', '@': '@.', 'O': '[]', '.': '..'}[c])
131+
new_floorplan.append(''.join(new_row))
132+
floorplan = new_floorplan
63133

64-
def main():
65-
warehouse, instructions = aoc.read_sections()
66-
warehouse = Grid(warehouse.splitlines())
134+
warehouse = Grid(floorplan)
67135
robot = None
68136
boxes = []
69137
for cell, pos in warehouse.by_cell():
138+
if cell == ']':
139+
warehouse[pos] = warehouse[Vec2(pos) + Dir.WEST]
140+
warehouse[pos].width = 2
141+
continue
70142
warehouse[pos] = convert(cell, pos)
71143
if type(warehouse[pos]) is Box:
72144
boxes.append(warehouse[pos])
73145
elif type(warehouse[pos]) is Robot:
74146
robot = warehouse[pos]
147+
return warehouse, robot, boxes
75148

76-
if aoc.args.verbose or aoc.args.progress:
77-
print(warehouse)
78149

79-
for instr in instructions:
80-
if instr == '\n':
81-
continue
82-
robot.move(Dir.map_nswe('^v<>')[instr], warehouse)
150+
def convert(cell: str, pos: Vec2) -> Robot | Box | Wall | Air:
151+
return {
152+
'@': Robot,
153+
'O': Box,
154+
'[': Box,
155+
'#': Wall,
156+
'.': Air
157+
}[cell](pos)
83158

84-
if aoc.args.verbose or aoc.args.progress:
85-
print(warehouse)
86159

87-
print(f"p1: {sum(box.pos.y * 100 + box.pos.x for box in boxes)}")
160+
def main():
161+
floorplan, instructions = aoc.read_sections()
162+
163+
warehouse, robot, boxes = build_warehouse(floorplan)
164+
if aoc.args.verbose or aoc.args.progress:
165+
print(warehouse)
166+
robot.process(instructions, warehouse)
167+
if aoc.args.progress:
168+
print(warehouse)
169+
print(f"p1: {sum(box.gps() for box in boxes)}")
170+
171+
warehouse, robot, boxes = build_warehouse(floorplan, wide=True)
172+
if aoc.args.verbose or aoc.args.progress:
173+
print(warehouse)
174+
robot.process(instructions, warehouse)
175+
if aoc.args.progress:
176+
print(warehouse)
177+
print(f"p2: {sum(box.gps() for box in boxes)}")
88178

89179

90180
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 - 190/480 ⭐
6+
Advent of Code - 191/480 ⭐
77
</h1>
88
<h1 align="center">
9-
2024 - 29 ⭐ - Python
9+
2024 - 30 ⭐ - 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)