Refactor 2024:15

Solution is still 100 lines, but now it is based
on a singular BFS oriented box push algorithm.
This commit is contained in:
Anders Englöf Ytterström 2024-12-18 12:35:33 +01:00
parent 7688ddb763
commit f5c3ee938a
2 changed files with 47 additions and 75 deletions

View file

@ -16,7 +16,9 @@ except ValueError:
name = None name = None
print( print(
f"\nAdvent of Code {year}" "\n###################" "\n\nby Anders Englöf Ytterström" f"\n\033[95m\033[1mAdvent of Code {year}\033[0m"
"\n###################"
"\n\n\033[96mby Anders Englöf Ytterström\033[0m"
) )
Path("./input").mkdir(parents=True, exist_ok=True) Path("./input").mkdir(parents=True, exist_ok=True)
@ -110,10 +112,10 @@ for i in [str(n).zfill(2) for n in range(1, 26)]:
except AttributeError: except AttributeError:
pass pass
if p1: if p1:
print(f" 1) {p1}") print(f" \033[92m1)\033[0m {p1}")
stars += 1 stars += 1
if p2: if p2:
print(f" 2) {p2}") print(f" \033[92m2)\033[0m {p2}")
stars += 1 stars += 1
except IOError: except IOError:
pass pass

View file

@ -33,101 +33,71 @@ def solve(data):
for move in movements: for move in movements:
r, c = pos r, c = pos
dr, dc = O[move] dr, dc = O[move]
moved = False move_boxes = True
blocked = False
match move: if (r + dr, c + dc) not in grid:
case "^":
targets = [((v, c), grid[(v, c)]) for v in range(r)][::-1]
case "<":
targets = [((r, v), grid[(r, v)]) for v in range(c)][::-1]
case "v":
targets = [((v, c), grid[(v, c)]) for v in range(r + 1, H)]
case ">":
targets = [((r, v), grid[(r, v)]) for v in range(c + 1, W)]
if "." not in map(lambda pv: pv[1], targets):
continue continue
if grid[(r + dr, c + dc)] == ".": match grid[(r + dr, c + dc)]:
moved = True case ".":
move_boxes = False
case "#":
move_boxes = False
continue
if grid[(r + dr, c + dc)] == "O" or ( if move_boxes:
grid[(r + dr, c + dc)] in "[]" and dc != 0 seen = set()
):
canmove = False
flips = []
for tpos, tvalue in targets: Q = [(r + dr, c + dc)]
flips.append((tpos, tvalue))
if tvalue == "#":
break
if tvalue == ".":
canmove = True
break
if canmove:
rotated = [value for _, value in flips]
rotated = rotated[-1:] + rotated[:-1]
for offset, pos in enumerate(flips):
grid[pos[0]] = rotated[offset]
moved = True
if grid[(r + dr, c + dc)] in "[]" and dc == 0 and dr != 0:
canmove = True
bs = set()
bmod = O[move][0]
Q = [(r + bmod, c)]
while Q: while Q:
rr, cc = Q.pop(0) rr, cc = Q.pop(0)
if (rr, cc) in bs: if (rr, cc) in seen:
continue continue
bs.add((rr, cc)) if (rr, cc) not in grid:
continue
if grid[(rr, cc)] == "#": if grid[(rr, cc)] == "#":
canmove = False blocked = True
continue continue
if grid[(rr, cc)] in "@.": seen.add((rr, cc))
if grid[(rr, cc)] in ".":
continue continue
match grid[(rr, cc)]: Q.append((rr + dr, cc + dc))
case "]": if dr != 0:
Q.append((rr + bmod, cc)) match grid[(rr, cc)]:
Q.append((rr, cc - 1)) case "]":
case "[": Q.append((rr, cc - 1))
Q.append((rr + bmod, cc)) case "[":
Q.append((rr, cc + 1)) Q.append((rr, cc + 1))
if canmove: if blocked:
patchset = { continue
(rr, cc): (rr + bmod, cc)
for rr, cc in bs
if grid[(rr, cc)] != "."
}
dotset = set(bs) - set(patchset.values()) patchset = {
(rr, cc): (rr + dr, cc + dc)
for rr, cc in seen
if grid[(rr, cc)] != "."
}
for psf, pst in sorted(patchset.items())[::-bmod]: dotset = set(seen) - set(patchset.values())
psnv = grid[psf]
grid[pst] = psnv
for rk in dotset: for oldpos, newpos in sorted(patchset.items())[:: -(dr + dc)]:
grid[rk] = "." value = grid[oldpos]
grid[newpos] = value
moved = True for dot in dotset:
grid[dot] = "."
if moved: grid[(r, c)] = "."
grid[(r, c)] = "." grid[(r + dr, c + dc)] = "@"
grid[(r + dr, c + dc)] = "@" pos = r + dr, c + dc
pos = r + dr, c + dc
answers.append(sum(k[0] * 100 + k[1] for k, v in grid.items() if v in "O[")) answers.append(sum(k[0] * 100 + k[1] for k, v in grid.items() if v in "O["))