Skip to content

Commit

Permalink
2024 day 15
Browse files Browse the repository at this point in the history
  • Loading branch information
agagniere committed Dec 24, 2024
1 parent 4b7fa3b commit cefec22
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 3 deletions.
62 changes: 62 additions & 0 deletions 2024/15/first.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from utils import Point, lines
from collections import defaultdict

EMPTY = 0
WALL = 1
BOX = 2

def direction(move: str):
return {
'>': (1, 0),
'<': (-1, 0),
'^': (0, -1),
'v': (0, 1),
}[move]

def parse(lines):
board = defaultdict(int)
robot = None
M = Point(0, 0)
for y, line in enumerate(lines):
print(line)
if not line:
M.y = y
break
for x, c in enumerate(line):
if c == '#':
board[Point(x,y)] = WALL
elif c == 'O':
board[Point(x,y)] = BOX
elif c == '@':
robot = Point(x, y)
M.x = max(x, M.x)

return board, robot, M + (1,0)

def move(board: dict, robot: Point, m: str):
d = direction(m)
dest = robot + d
freespot = dest
while board[freespot] == BOX:
freespot += d
if board[freespot] != WALL:
if dest != freespot:
board[freespot] = BOX
board[dest] = EMPTY
robot = dest
return board, robot

if __name__ == '__main__':
board, robot, bounds = parse(lines())
for line in lines():
for m in line:
board, robot = move(board, robot, m)
for y in range(bounds.y):
print(''.join('#' if board[(x,y)] == WALL else
'O' if board[(x,y)] == BOX else '.'
for x in range(bounds.x)))
R = 0
for pos, item in board.items():
if item == BOX:
R += pos.y * 100 + pos.x
print(R)
101 changes: 101 additions & 0 deletions 2024/15/second.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from utils import Point, lines
from collections import defaultdict

EMPTY = 0
WALL = 1
BOX_LEFT = 2
BOX_RIGHT = 3

def direction(move: str):
return {
'>': (1, 0),
'<': (-1, 0),
'^': (0, -1),
'v': (0, 1),
}[move]

def parse(lines):
board = defaultdict(int)
robot = None
M = Point(0, 0)
for y, line in enumerate(lines):
#print(line)
if not line:
M.y = y
break
for x, c in enumerate(line):
P = Point(2*x, y)
if c == '#':
board[P] = WALL
board[P + (1, 0)] = WALL
elif c == 'O':
board[P] = BOX_LEFT
board[P + (1, 0)] = BOX_RIGHT
elif c == '@':
robot = P
M.x = max(M.x, P.x)
return board, robot, M + (1,0)

BOX_PART = set([BOX_LEFT, BOX_RIGHT])

def move(board: dict, robot: Point, m: str):
d = direction(m)
dest = robot + d
to_move = []
freespots = [dest]

while True:
obs = set(board[s] for s in freespots)
if WALL in obs:
return board, robot
elif BOX_PART & obs:
match m:
case '<':
for f in freespots:
to_move += [f, f + (-1, 0)]
freespots = [f + (-2, 0) for f in freespots]
case '>':
for f in freespots:
to_move += [f, f + (1, 0)]
freespots = [f + (2, 0) for f in freespots]
case '^':
nf = []
for f in freespots:
if board[f] == BOX_LEFT and f + (0, -1) not in nf:
to_move += [f, f + (1, 0)]
nf += [f + (0, -1), f + (1, -1)]
elif board[f] == BOX_RIGHT and f + (0, -1) not in nf:
to_move += [f, f + (-1, 0)]
nf += [f + (0, -1), f + (-1, -1)]
freespots = nf
case 'v':
nf = []
for f in freespots:
if board[f] == BOX_LEFT and f + (0, 1) not in nf:
to_move += [f, f + (1, 0)]
nf += [f + (0, 1), f + (1, 1)]
elif board[f] == BOX_RIGHT and f + (0, 1) not in nf:
to_move += [f, f + (-1, 0)]
nf += [f + (0, 1), f + (-1, 1)]
freespots = nf
else:
for p in reversed(to_move):
board[p+d] = board[p]
board[p] = EMPTY
return board, robot + d

if __name__ == '__main__':
board, robot, bounds = parse(lines())
for line in lines():
for m in line:
board, robot = move(board, robot, m)
# for y in range(bounds.y):
# print(''.join('#' if board[(x,y)] == WALL else
# '[' if board[(x,y)] == BOX_LEFT else
# ']' if board[(x,y)] == BOX_RIGHT else '.'
# for x in range(bounds.x)))
R = 0
for pos, item in board.items():
if item == BOX_LEFT:
R += pos.y * 100 + pos.x
print(R)
25 changes: 25 additions & 0 deletions 2024/15/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
def lines():
while True:
try:
yield input()
except:
break

class Point:
__match_args__ = ['x', 'y']

def __init__(self, x, y): self.x, self.y = x, y
def neighbors(self):
for d in ((-1, 0), (1, 0), (0, -1), (0, 1)):
yield self + d
def __add__(self, other): return Point(self.x + other[0], self.y + other[1])
def __mul__(self, sca): return Point(self.x * sca, self.y * sca)
def __sub__(self, other): return Point(self.x - other[0], self.y - other[1])
def __neg__(self): return Point(-self.x, -self.y)
def __eq__(self, other): return self.x == other[0] and self.y == other[1]
def __getitem__(self, i): return self.x if i == 0 else self.y
def __str__(self): return "({}, {})".format(self.x, self.y)
def __repr__(self): return "({} {})".format(self.x, self.y)
def __hash__(self): return (self.x, self.y).__hash__()
def __lt__(self, other): return (self.x, self.y) < (other[0], other[1])
def __mod__(self, other): return Point(self.x % other[0], self.y % other[1])
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ My solutions for the [Advent of Code](https://adventofcode.com), a challenge sta
| 12 |||||:star::star:|:star::star:|:star::star:|:star::star:|
| 13 |||||:star::star:|:star::star:|:star::star:|:star::star:|:star::star:
| 14 |||||:star::star:|:star::star:|:star::star:|:star::star:|
| 15 |||||:star::star:|:star::star:|:star::star:|:star::star:|
| 15 |||||:star::star:|:star::star:|:star::star:|:star::star:|:star::star:
| 16 |||||:star::star:|:star::star:|:star::star:|:star::star:|:star::star:
| 17 |||||:star::star:|:star::star:|:star::star:|:star::star:|
| 18 |||||:star::star:|:star::star:|:star::star:|:star::star:|
Expand All @@ -30,6 +30,6 @@ My solutions for the [Advent of Code](https://adventofcode.com), a challenge sta
| 23 |||||||:star::star:|:star:|
| 24 |||||:star::star:|:star::star:|:star::star:|:star:|
| 25 |||||:star:|:star:|:star::star:||
| Total | 10 | 14 | 4 | 12 | 46 | 44 | 50 | 44 | 24
| Total | 10 | 14 | 4 | 12 | 46 | 44 | 50 | 44 | 26

Total stars: 248
Total stars: 250

0 comments on commit cefec22

Please sign in to comment.