-
Notifications
You must be signed in to change notification settings - Fork 0
/
day15.py
103 lines (91 loc) · 3.39 KB
/
day15.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from aoc_utils import *
grid, moves = open("inputs/day15.txt").read().split("\n\n")
moves = moves.replace("\n", "")
def part1(grid, moves):
pos = grid_find(grid, "@")
grid = complex_grid(grid.split("\n"), filter="#O")
for move in moves:
dir = dir_map[move]
pos_, start, end = pos, 0, 0
while True:
pos_ += dir
if pos_ not in grid:
pos += dir
if start:
del grid[start]
grid[end + dir] = "O"
break
elif grid[pos_] == "O":
if not start:
start = pos_
end = pos_
elif grid[pos_] == "#":
break
return grid
def part2(grid, moves):
grid = grid.translate(str.maketrans({"#": "##", "O": "[]", ".": "..", "@": "@."}))
pos = grid_find(grid, "@")
grid = complex_grid(grid.split("\n"), filter="#[]")
for move in moves:
dir = dir_map[move]
boxes = {}
pos_ = pos + dir
if pos_ not in grid:
pos = pos_
elif grid.get(pos_, ".") in "[]":
# Find connected components (boxes)
change = True
if dir.real: # Move horizontal
while True:
match grid.get(pos_, None):
case None:
break
case "[" | "]":
boxes[pos_] = grid[pos_]
pos_ += dir
case "#":
change = False
break
else: # Move Vertical
if grid[pos_] == "]":
pos_ = pos_ - 1
boxes[pos_] = "["
boxes[pos_ + 1] = "]"
front = {pos_}
while change:
front_ = set()
for pos_ in front:
if (
grid.get(pos_ + dir) == "#"
or grid.get(pos_ + 1 + dir) == "#"
):
change = False
break
elif grid.get(pos_ + dir) == "[":
boxes[pos_ + dir] = "["
boxes[pos_ + dir + 1] = "]"
front_.add(pos_ + dir)
else:
if grid.get(pos_ + dir) == "]":
boxes[pos_ + dir] = "]"
boxes[pos_ + dir - 1] = "["
front_.add(pos_ + dir - 1)
if grid.get(pos_ + dir + 1) == "[":
boxes[pos_ + dir + 1] = "["
boxes[pos_ + dir + 2] = "]"
front_.add(pos_ + dir + 1)
if front_:
front = front_
else:
break
if change:
pos += dir
for p in boxes:
del grid[p]
for p, item in boxes.items():
grid[p + dir] = item
return grid
def coords_sum(grid):
return int(sum(pos.imag * 100 + pos.real for pos, c in grid.items() if c in "O["))
print(coords_sum(part1(grid, moves)))
print(coords_sum(part2(grid, moves)))