Finish 2016.

This commit is contained in:
felixm 2024-05-20 20:00:34 -04:00
parent 90b2134736
commit 6f63a866e1
5 changed files with 301 additions and 1 deletions

89
2016/d22.py Normal file
View File

@ -0,0 +1,89 @@
from lib import str_to_ints
from dataclasses import dataclass
from collections import defaultdict
data = """ Filesystem Size Used Avail Use%
/dev/grid/node-x0-y0 10T 8T 2T 80%
/dev/grid/node-x0-y1 11T 6T 5T 54%
/dev/grid/node-x0-y2 32T 28T 4T 87%
/dev/grid/node-x1-y0 9T 7T 2T 77%
/dev/grid/node-x1-y1 8T 0T 8T 0%
/dev/grid/node-x1-y2 11T 7T 4T 63%
/dev/grid/node-x2-y0 10T 6T 4T 60%
/dev/grid/node-x2-y1 9T 8T 1T 88%
/dev/grid/node-x2-y2 9T 6T 3T 66%
"""
@dataclass
class Node:
id: int
x: int
y: int
size: int
used: int
avail: int
usep: int
def get_nodes(data):
return [Node(i, *str_to_ints(line)) for i, line in enumerate(data.splitlines()[2:])]
def part_1(data):
c = 0
nodes = get_nodes(data)
for a in nodes:
for b in nodes:
if a is not b and a.used != 0 and a.used <= b.avail:
c += 1
print(c)
def part_2(data):
nodes = get_nodes(data)
empty = None
for n in nodes:
if n.usep < 50:
assert empty is None
empty = (n.x, n.y)
assert empty is not None
grid = defaultdict(dict)
for n in nodes:
grid[n.x][n.y] = n
cols = len(grid)
steps = 0
steps += empty[1] # move space to y=0
steps += ((cols - 2) - empty[0]) # move space to x=cols-1
# shuffle target cell to (0, 0) via empty space
steps += ((cols - 2) * 5)
steps += 1
# Account for the fact that there is a "barrier" through which we cannot
# move the space. This can be seen by uncommenting the grid print code
# below. Might have been better to code a proper search from the beginning.
# Clearly he enjoyed setting a bit of a trap there.
steps += 15 - 3
# for y in range(rows):
# for x in range(cols):
# print(f"{grid[x][y].used:2} ", end='')
# print()
print(steps)
def main():
data = open(0).read().strip()
part_1(data)
part_2(data)
if __name__ == "__main__":
main()

87
2016/d23.py Normal file
View File

@ -0,0 +1,87 @@
from math import factorial
def solve(data, part_2=False):
REGS = "abcd"
regs = {c: 0 for c in REGS}
if part_2:
print(factorial(12) + (91 * 85))
return
else:
regs["a"] = 7
insts = data.splitlines()
i = 0
inst_count = 0
while i < len(insts):
inst_count += 1
# print(i, regs)
parts = insts[i].split()
cmd = parts[0]
if cmd == "cpy":
if parts[1] in REGS:
regs[parts[2]] = regs[parts[1]]
else:
regs[parts[2]] = int(parts[1])
elif cmd == "jnz":
val = 0
if parts[1] in REGS:
val = regs[parts[1]]
else:
val = int(parts[1])
if val != 0:
if parts[2] in REGS:
i += regs[parts[2]]
else:
i += int(parts[2])
continue
elif cmd == "inc":
if insts[i + 1] == "dec d" and insts[i + 2] == "jnz d -2":
regs[parts[1]] += regs["d"]
regs["d"] = 0
i += 3
continue
regs[parts[1]] += 1
elif cmd == "dec":
regs[parts[1]] -= 1
elif cmd == "tgl":
off = 0
if parts[1] in REGS:
off = regs[parts[1]]
else:
off = int(parts[1])
addr = i + off
if addr < len(insts):
parts = insts[addr].split()
if len(parts) == 2:
if parts[0] == "inc":
parts[0] = "dec"
else:
parts[0] = "inc"
insts[addr] = " ".join(parts)
elif len(parts) == 3:
if parts[0] == "jnz":
parts[0] = "cpy"
else:
parts[0] = "jnz"
insts[addr] = " ".join(parts)
else:
assert False
else:
assert False
i += 1
print(regs["a"])
def main():
data = open(0).read().strip()
solve(data)
solve(data, True)
if __name__ == "__main__":
main()

61
2016/d24.py Normal file
View File

@ -0,0 +1,61 @@
from collections import deque, defaultdict
from itertools import permutations
from lib import Grid2D, INF
def shortest_path(grid, start, end):
seen = set()
open = deque([(start, 0)])
while open:
current, steps = open.popleft()
if current in seen:
continue
seen.add(current)
if current == end:
return steps
for nb in grid.neighbors_ort(current):
if grid[nb] == "#":
continue
open.append((nb, steps + 1))
return None
def solve(data, part_2=False):
g = Grid2D(data)
# g.print()
start = g.find("0")[0]
points = g.find_not("#.")
shortest = defaultdict(defaultdict)
for i in range(len(points)):
for j in range(i + 1, len(points)):
a, b = points[i], points[j]
s = shortest_path(g, a, b)
assert s is not None
shortest[a][b] = s
shortest[b][a] = s
# Brute force all combinations.
points.remove(start)
dmin = INF
for p in permutations(points):
d = 0
d += shortest[start][p[0]]
for i in range(len(p) - 1):
d += shortest[p[i]][p[i + 1]]
if part_2:
d += shortest[p[-1]][start]
dmin = min(d, dmin)
print(dmin)
return
def main():
data = open(0).read().strip()
solve(data)
solve(data, True)
if __name__ == "__main__":
main()

60
2016/d25.py Normal file
View File

@ -0,0 +1,60 @@
def solve(data):
REGS = "abcd"
goal = [0, 1, 0, 1, 0, 1, 0, 1]
for a in range(0, 1000):
insts = data.splitlines()
regs = {c: 0 for c in REGS}
regs["a"] = a
outs = []
i = 0
inst_count = 0
while i < len(insts):
inst_count += 1
if inst_count > 100_000:
break
parts = insts[i].split()
cmd = parts[0]
if cmd == "cpy":
if parts[1] in "abcd":
regs[parts[2]] = regs[parts[1]]
else:
regs[parts[2]] = int(parts[1])
elif cmd == "out":
if parts[1] in "abcd":
v = regs[parts[1]]
else:
v = int(parts[1])
outs.append(v)
if len(outs) == len(goal):
if outs == goal:
print(a)
return
else:
# print(outs)
pass
elif cmd == "jnz":
val = 0
if parts[1] in "abcd":
val = regs[parts[1]]
else:
val = int(parts[1])
if val != 0:
i += int(parts[2])
continue
elif cmd == "inc":
regs[parts[1]] += 1
elif cmd == "dec":
regs[parts[1]] -= 1
else:
assert False
i += 1
def main():
data = open(0).read().strip()
solve(data)
if __name__ == "__main__":
main()

View File

@ -54,7 +54,10 @@ written in Python.
- Day 19: 90:00 that wasn't easy for me
- Day 20: 67:00
- Day 21: 32:33
- Day 22:
- Day 22: 90:00
- Day 23: 60:00
- Day 24: 48:00
- Day 25:
# 2017