Compare commits

..

2 commits

Author SHA1 Message Date
89e2c58a78 Add day 16 2023-12-29 23:39:23 +01:00
14354c85b8 Catch up to day 15 2023-12-29 22:03:50 +01:00
10 changed files with 476 additions and 0 deletions

3
.gitignore vendored
View file

@ -1,3 +1,6 @@
*.in
*.ex*
day??
*.prof
*.lprof

25
day09.py Normal file
View file

@ -0,0 +1,25 @@
import fileinput
from collections import deque
def main():
part1 = 0
part2 = 0
for line in fileinput.input():
values = deque(int(t) for t in line.split())
stack = [values]
while any(values):
values = deque(values[i + 1] - values[i] for i in range(len(values) - 1))
stack.append(values)
for i in range(len(stack) - 1, 0, -1):
stack[i - 1].append(stack[i - 1][-1] + stack[i][-1])
stack[i - 1].appendleft(stack[i - 1][0] - stack[i][0])
part1 += stack[0][-1]
part2 += stack[0][0]
print(part1, part2)
main()

151
day10.py Normal file
View file

@ -0,0 +1,151 @@
from collections import deque
import fileinput
from pprint import pprint
from dataclasses import dataclass
map = []
(sx, sy) = (0, 0)
for (j, line) in enumerate(fileinput.input()):
map.append(list(line.strip()))
if (x := line.find("S")) != -1:
(sx, sy) = (x, j)
seen = set()
queue: deque[tuple[int, int, int]] = deque([(sx, sy, 0)])
distances = [[None] * len(map[0]) for _ in range(len(map))]
NS = "|"
WE = "-"
NE = "L"
NW = "J"
SW = "7"
SE = "F"
part1 = 0
while queue:
(x, y, l) = queue.popleft()
if (x, y) in seen:
continue
seen.add((x, y))
distances[y][x] = l
part1 = l
match map[y][x]:
case "S":
if map[y - 1][x] in "|7F":
queue.append((x, y - 1, l + 1))
if map[y + 1][x] in "|LJ":
queue.append((x, y + 1, l + 1))
if map[y][x - 1] in "-LF":
queue.append((x - 1, y, l + 1))
if map[y][x + 1] in "-J7":
queue.append((x + 1, y, l + 1))
case "|":
queue.append((x, y - 1, l + 1))
queue.append((x, y + 1, l + 1))
case "-":
queue.append((x - 1, y, l + 1))
queue.append((x + 1, y, l + 1))
case "L":
queue.append((x + 1, y, l + 1))
queue.append((x, y - 1, l + 1))
case "J":
queue.append((x - 1, y, l + 1))
queue.append((x, y - 1, l + 1))
case "7":
queue.append((x - 1, y, l + 1))
queue.append((x, y + 1, l + 1))
case "F":
queue.append((x + 1, y, l + 1))
queue.append((x, y + 1, l + 1))
part1 = 0
for l in distances:
part1 = max(part1, 0, *[i for i in l if i])
print(part1)
side = set()
for y in range(len(map)):
if map[y][0] == ".": side.add((0, y))
if map[y][-1] == ".": side.add((len(map[0]) - 1, y))
for x in range(len(map[0])):
if map[0][x] == ".": side.add((x, 0))
if map[-1][x] == ".": side.add((x, len(map) - 1))
mapp = []
for (x, row) in enumerate(map):
r = []
for (y, c) in enumerate(row):
match c:
case ".":
r.append(["..."]*3)
case "S":
r.append([".X.","XXX",".X."])
case "-":
r.append(["...","XXX","..."])
case "|":
r.append([".X.",".X.",".X."])
case "7":
r.append(["...","XX.",".X."])
case "F":
r.append(["...",".XX",".X."])
case "J":
r.append([".X.","XX.","..."])
case "L":
r.append([".X.",".XX","..."])
mapp.append(r)
bigmap = []
for row in mapp:
for y in range(3):
r = []
for col in row:
for x in range(3):
r.append(col[y][x])
bigmap.append(r)
print(r)
exterior = []
for y in range(len(bigmap)):
if bigmap[y][0] == ".":
exterior.append((0, y))
if bigmap[y][-1] == ".":
exterior.append((len(bigmap[0]) - 1, y))
for x in range(len(bigmap[0])):
if bigmap[0][x] == ".":
exterior.append((x, 0))
if bigmap[-1][x] == ".":
exterior.append((x, len(bigmap) - 1))
for (x, y) in exterior:
if y < 0 or y > len(bigmap) - 1:
continue
if x < 0 or x > len(bigmap[y]) - 1:
continue
if bigmap[y][x] != ".":
continue
bigmap[y][x] = "O"
exterior.append((x - 1, y))
exterior.append((x + 1, y))
exterior.append((x, y - 1))
exterior.append((x, y + 1))
for row in distances:
for c in row:
print("X" if c is not None else ".", end="")
print()
part2 = 0
for y in range(1, len(bigmap), 3):
for x in range(1, len(bigmap[y]), 3):
if bigmap[y][x] == "." or (distances[y // 3][x // 3] is None):
part2 += 1
map[y//3][x//3] = 'I'
print(part1, part2)

76
day11.py Normal file
View file

@ -0,0 +1,76 @@
import fileinput
import math
from pprint import pprint
from itertools import pairwise
def main():
(part1, part2) = (0, 0)
# parse
inp = fileinput.input()
coords_ = []
(w, h) = (0, 0)
for (y, row) in enumerate(inp):
for (x, c) in enumerate(row):
if c == "#":
coords_.append((x, y))
w = max(w, x)
h = max(h, y)
coords = coords_.copy()
(dx, dy) = (0, 0)
for j in range(h):
if not any(y_ == j + dy for (_, y_) in coords):
print(f"inserting row at y={j}")
for i in range(len(coords)):
(x_, y_) = coords[i]
if y_ > j + dy:
coords[i] = (x_, y_ + 1)
dy += 1
if not any(x_ == j + dx for (x_, _) in coords):
print(f"inserting column at x={j}")
for i in range(len(coords)):
(x_, y_) = coords[i]
if x_ > j + dx:
coords[i] = (x_ + 1, y_)
dx += 1
part1 = 0
for ai in range(len(coords)):
for bi in range(ai + 1, len(coords)):
(ax, ay) = coords[ai]
(bx, by) = coords[bi]
part1 += abs(ax - bx) + abs(ay - by)
coords = coords_.copy()
L = 1_000_000 - 1
(dx, dy) = (0, 0)
for j in range(h):
if not any(y_ == j + dy for (_, y_) in coords):
print(f"inserting rows at y={j}")
for i in range(len(coords)):
(x_, y_) = coords[i]
if y_ > j + dy:
coords[i] = (x_, y_ + L)
dy += L
if not any(x_ == j + dx for (x_, _) in coords):
print(f"inserting columns at x={j}")
for i in range(len(coords)):
(x_, y_) = coords[i]
if x_ > j + dx:
coords[i] = (x_ + L, y_)
dx += L
part2 = 0
for ai in range(len(coords)):
for bi in range(ai + 1, len(coords)):
(ax, ay) = coords[ai]
(bx, by) = coords[bi]
part2 += abs(ax - bx) + abs(ay - by)
print(part1, part2)
if __name__ == "__main__":
main()

34
day12.py Normal file
View file

@ -0,0 +1,34 @@
import fileinput
import math
from pprint import pprint
from itertools import chain, combinations, count, groupby
import re
RE = re.compile(r"[#\?]")
def powerset(iterable):
"powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
def main():
(part1, part2) = (0, 0)
inp = fileinput.input()
for line in inp:
(springs, groups) = line.split()
groups = [int(g) for g in groups.split(",")]
unknowns = [x for (x, c) in enumerate(springs) if c == "?"]
springs_ = springs.replace("?", ".")
for xs in powerset(unknowns):
h = "".join("#" if i in xs else c for (i, c) in enumerate(springs_))
match = [len(g) for g in RE.findall(h)]
if match == groups:
part1 += 1
print(part1, part2)
if __name__ == "__main__":
main()

47
day13.py Normal file
View file

@ -0,0 +1,47 @@
import sys
import numpy as np
# @profile
def main():
with open(sys.argv[1]) as f:
inp = [
[[c == "#" for c in line] for line in field.split("\n")]
for field in f.read().strip().split("\n\n")
]
(part1, part2) = (0, 0)
for field in inp:
field = np.array(field)
(h, w) = field.shape
(x1, y1, x2, y2) = (0, 0, 0, 0)
for x in range(1, w):
w2 = min(x, w - x)
left = field[:, (x - w2) : x]
right = field[:, x : (x + w2)][:, ::-1]
mismatches = (left != right).sum()
if not x2 and mismatches == 1:
x2 = x
elif not x1 and mismatches == 0:
x1 = x
if not x1 or not x2:
for y in range(1, h):
h2 = min(y, h - y)
left = field[(y - h2) : y]
right = field[y : (y + h2)][::-1]
mismatches = (left != right).sum()
if not y2 and mismatches == 1:
y2 = y
elif not y1 and mismatches == 0:
y1 = y
part1 += x1 + y1 * 100
part2 += x2 + y2 * 100
print(part1, part2)
main()

47
day15.py Normal file
View file

@ -0,0 +1,47 @@
import os
import sys
from collections import defaultdict
def hash(s):
v = 0
for c in s:
if c == ",":
continue
v += ord(c)
v *= 17
v %= 256
return v
with open(sys.argv[1]) as f:
s = f.read().strip()
boxes = defaultdict(list)
part1 = 0
for s_ in s.split(","):
part1 += hash(s_)
if s_[-1] == "-":
label = s_[:-1]
h = hash(label)
for i in range(len(boxes[h])):
if boxes[h][i][0] == label:
del boxes[h][i]
break
elif s_[-2] == "=":
label = s_[:-2]
focal = int(s_[-1])
h = hash(label)
for i in range(len(boxes[h])):
if boxes[h][i][0] == label:
boxes[h][i] = (label, focal)
break
else:
boxes[h].append((label, focal))
part2 = 0
for (box_i, box) in boxes.items():
for (slot, (_, focal)) in enumerate(box):
part2 += (box_i + 1) * (slot + 1) * focal
print(part1, part2)

76
day16.py Normal file
View file

@ -0,0 +1,76 @@
import sys
def simulate(map, entry):
seen = set()
energised = set()
stack: list[tuple[tuple[int, int], tuple[int, int]]] = [entry]
while stack:
entry = stack.pop()
if entry in seen:
continue
seen.add(entry)
((x, y), (dx, dy)) = entry
if not (0 <= y < len(map)) or not (0 <= x < len(map[y])):
continue
energised.add((x, y))
match map[y][x]:
case ".":
stack.append(((x + dx, y + dy), (dx, dy)))
case "-" if dy == 0:
stack.append(((x + dx, y + dy), (dx, dy)))
case "-":
stack.append(((x - 1, y), (-1, 0)))
stack.append(((x + 1, y), (1, 0)))
case "|" if dx == 0:
stack.append(((x + dx, y + dy), (dx, dy)))
case "|":
stack.append(((x, y - 1), (0, -1)))
stack.append(((x, y + 1), (0, 1)))
case "/" if (dx, dy) == (1, 0):
stack.append(((x, y - 1), (0, -1)))
case "/" if (dx, dy) == (-1, 0):
stack.append(((x, y + 1), (0, 1)))
case "/" if (dx, dy) == (0, 1):
stack.append(((x - 1, y), (-1, 0)))
case "/" if (dx, dy) == (0, -1):
stack.append(((x + 1, y), (1, 0)))
case "\\" if (dx, dy) == (1, 0):
stack.append(((x, y + 1), (0, 1)))
case "\\" if (dx, dy) == (-1, 0):
stack.append(((x, y - 1), (0, -1)))
case "\\" if (dx, dy) == (0, 1):
stack.append(((x + 1, y), (1, 0)))
case "\\" if (dx, dy) == (0, -1):
stack.append(((x - 1, y), (-1, 0)))
return len(energised)
def main():
with open(sys.argv[1]) as f:
map = [list(l) for l in f.read().strip().splitlines()]
part1 = simulate(map, ((0, 0), (1, 0)))
part2 = 0
for y in range(len(map)):
w = len(map[y])
xp = simulate(map, ((0, y), (1, 0)))
xm = simulate(map, ((w - 1, y), (-1, 0)))
part2 = max(part2, xp, xm)
for x in range(len(map)):
h = len(map)
yp = simulate(map, ((x, 0), (0, 1)))
ym = simulate(map, ((x, h - 1), (0, -1)))
part2 = max(part2, yp, ym)
print(part1, part2)
if __name__ == "__main__":
main()

2
empty.py Normal file
View file

@ -0,0 +1,2 @@
import fileinput
list(fileinput.input())

15
template.py Normal file
View file

@ -0,0 +1,15 @@
import fileinput
import math
from pprint import pprint
def main():
(part1, part2) = (0, 0)
inp = fileinput.input()
for line in inp:
pass
print(part1, part2)
if __name__ == "__main__":
main()