-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathp15.py
133 lines (107 loc) · 3.52 KB
/
p15.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
from collections import deque
from aocd import data
def move_boxes(x, y, i, j):
nx, ny = x + i, y + j
if warehouse[(nx, ny)] == ".":
warehouse[(nx, ny)] = warehouse[(x, y)]
warehouse[(x, y)] = "."
return True
elif warehouse[(nx, ny)] == "#":
return False
elif warehouse[(nx, ny)] == "O":
moved = move_boxes(nx, ny, i, j)
if moved:
warehouse[(nx, ny)] = warehouse[(x, y)]
warehouse[(x, y)] = "."
return moved
def can_move_up_down(x, y, j):
queue = deque([(x, y)])
while queue:
x, y = queue.popleft()
if wide_warehouse[(x, y+j)] == "#":
return False
if wide_warehouse[(x, y+j)] == "[":
queue.append((x, y+j))
queue.append((x+1, y+j))
elif wide_warehouse[(x, y+j)] == "]":
queue.append((x, y+j))
queue.append((x-1, y+j))
return True
def can_move_left_right(x, y, i):
x += i
while wide_warehouse[(x, y)] not in "#.":
x += i
return wide_warehouse[(x, y)] == "."
def move_wide_boxes(x, y, i, j):
nx, ny = x + i, y + j
if wide_warehouse[(nx, ny)] == ".":
wide_warehouse[(nx, ny)] = wide_warehouse[(x, y)]
wide_warehouse[(x, y)] = "."
elif i:
move_wide_boxes(nx, ny, i, j)
wide_warehouse[(nx, ny)] = wide_warehouse[(x, y)]
wide_warehouse[(x, y)] = "."
elif wide_warehouse[(nx, ny)] == "[":
move_wide_boxes(nx, ny, i, j)
move_wide_boxes(nx+1, ny, i, j)
wide_warehouse[(nx, ny)] = wide_warehouse[(x, y)]
wide_warehouse[(x, y)] = "."
elif wide_warehouse[(nx, ny)] == "]":
move_wide_boxes(nx, ny, i, j)
move_wide_boxes(nx-1, ny, i, j)
wide_warehouse[(nx, ny)] = wide_warehouse[(x, y)]
wide_warehouse[(x, y)] = "."
warehouse_raw, moves = data.split("\n\n")
moves = moves.replace("\n", "")
warehouse = {}
for y, row in enumerate(warehouse_raw.splitlines()):
for x, col in enumerate(row):
warehouse[(x, y)] = col
if col == "@":
rx, ry = x, y
max_x, max_y = max(warehouse)
directions = {"^": (0, -1), "v": (0, 1), "<": (-1, 0), ">": (1, 0)}
x, y = rx, ry
for move in moves:
i, j = directions[move]
moved = move_boxes(x, y, i, j)
if moved:
x += i
y += j
boxes_coords_sum = 0
for y in range(max_y + 1):
for x in range(max_x + 1):
if warehouse[(x, y)] == "O":
boxes_coords_sum += y * 100 + x
print("Part 1:", boxes_coords_sum)
wide_warehouse = {}
for y, row in enumerate(warehouse_raw.splitlines()):
for x, col in enumerate(row):
if col == "#":
wide_warehouse[(x+x, y)] = "#"
wide_warehouse[(x+x+1, y)] = "#"
elif col == "@":
rx, ry = x+x, y
wide_warehouse[(x+x, y)] = "@"
wide_warehouse[(x+x+1, y)] = "."
elif col == ".":
wide_warehouse[(x+x, y)] = "."
wide_warehouse[(x+x+1, y)] = "."
elif col == "O":
wide_warehouse[(x+x, y)] = "["
wide_warehouse[(x+x+1, y)] = "]"
x, y = rx, ry
for move in moves:
i, j = directions[move]
if (i and can_move_left_right(x, y, i)
or j and can_move_up_down(x, y, j)):
move_wide_boxes(x, y, i, j)
x += i
y += j
max_x, max_y = max(wide_warehouse)
boxes_coords_sum = 0
for y in range(max_y + 1):
for x in range(max_x + 1):
if wide_warehouse[(x, y)] == "[":
boxes_coords_sum += y * 100 + x
print("Part 2:", boxes_coords_sum)