Finish 2016.
This commit is contained in:
parent
90b2134736
commit
6f63a866e1
89
2016/d22.py
Normal file
89
2016/d22.py
Normal 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
87
2016/d23.py
Normal 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
61
2016/d24.py
Normal 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
60
2016/d25.py
Normal 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()
|
Loading…
Reference in New Issue
Block a user