15
https://adventofcode.com/2024/day/15
Prob1
python
import sys
from typing import Tuple, Set
walls: Set[Tuple[int, int]] = set()
boxes: Set[Tuple[int, int]] = set()
op_list = ''
cur: Tuple[int, int] = (0, 0)
y = 0
for line in sys.stdin:
line = line.strip()
if line == '':
continue
if line.startswith('#'):
for x, ch in enumerate(line):
p = (x, y)
if ch == '#':
walls.add(p)
elif ch == 'O':
boxes.add(p)
elif ch == '@':
cur = p
y += 1
else:
op_list += line
print(walls)
print(boxes)
print(op_list)
dir_tab = {
'>': (1, 0),
'<': (-1, 0),
'v': (0, 1),
'^': (0, -1),
}
for op in op_list:
px, py = cur
dx, dy = dir_tab[op]
nx, ny = px + dx, py + dy
np = (nx, ny)
if np in walls:
continue
if np not in boxes:
cur = np
continue
affect_box: Tuple[int, int] = np
while True:
nx, ny = nx + dx, ny + dy
np = (nx, ny)
if np in boxes:
continue
if np in walls:
# ok, no move
break
# empty space, we can make a move!
cur = affect_box
boxes.remove(affect_box)
boxes.add(np)
break
ans = 0
for (bx, by) in boxes:
ans += 100*by + bx
print(ans)
Prob2
python
import sys
from queue import Queue
from typing import Tuple, Set, List
walls: Set[Tuple[int, int]] = set()
boxes: Set[Tuple[int, int]] = set()
op_list = ''
cur: Tuple[int, int] = (0, 0)
y = 0
for line in sys.stdin:
line = line.strip()
if line == '':
continue
if line.startswith('#'):
for x, ch in enumerate(line):
if ch == '#':
walls.add((2*x, y))
walls.add((2*x + 1, y))
elif ch == 'O':
boxes.add((2*x, y))
elif ch == '@':
cur = (2*x, y)
y += 1
else:
op_list += line
print(walls)
print(boxes)
print(op_list)
dir_tab = {
'>': (1, 0),
'<': (-1, 0),
'v': (0, 1),
'^': (0, -1),
}
for op in op_list:
dx, dy = dir_tab[op]
px, py = cur
nx, ny = px + dx, py + dy
np = (nx, ny)
if np in walls:
continue
affect_boxes: Set[Tuple[int, int]] = set()
visited_boxes: Set[Tuple[int, int]] = set()
affect_queue = Queue()
pushable = True
if np in boxes:
affect_boxes.add(np)
affect_queue.put(np)
n2p = (nx - 1, ny)
if n2p in boxes:
affect_boxes.add(n2p)
affect_queue.put(n2p)
while not affect_queue.empty():
px, py = affect_queue.get()
visited_boxes.add((px, py))
n1p = px + dx, py + dy
n2p = px + dx + 1, py + dy
n3p = px + dx - 1, py + dy
if n1p in walls or n2p in walls:
pushable = False
break
if n1p in boxes and n1p not in visited_boxes:
affect_boxes.add(n1p)
affect_queue.put(n1p)
if n2p in boxes and n2p not in visited_boxes:
affect_boxes.add(n2p)
affect_queue.put(n2p)
if n3p in boxes and n3p not in visited_boxes:
affect_boxes.add(n3p)
affect_queue.put(n3p)
if not pushable:
# print('not pushable')
continue
new_boxes: List[Tuple[int, int]] = []
for (bx, by) in affect_boxes:
new_boxes.append((bx + dx, by + dy))
print('affect', affect_boxes, '->', new_boxes)
for box in affect_boxes:
boxes.remove(box)
for box in new_boxes:
boxes.add(box)
px, py = cur
cur = (px + dx, py + dy)
# print(boxes)
print(boxes)
ans = 0
for (bx, by) in boxes:
ans += 100*by + bx
print(ans)