day 11 python cleanup
parent
eefab8eabf
commit
4fc545ac39
101
day11/sol.py
101
day11/sol.py
|
@ -1,54 +1,71 @@
|
||||||
from collections import Counter
|
from collections import Counter, namedtuple
|
||||||
|
import math
|
||||||
|
|
||||||
|
Monkey = namedtuple('Monkey', 'index, op, divisor, target')
|
||||||
def parse(input):
|
def parse(input):
|
||||||
if hasattr(input, 'read'):
|
|
||||||
input = input.read()
|
|
||||||
monkeys = []
|
monkeys = []
|
||||||
for chunk in input.split("\n\n"):
|
items = {}
|
||||||
|
for i, chunk in enumerate(input.split("\n\n")):
|
||||||
lines = chunk.strip().split("\n")
|
lines = chunk.strip().split("\n")
|
||||||
assert 'Starting' in lines[1]
|
assert 'Starting items:' in lines[1]
|
||||||
items = [int(x.strip()) for x in lines[1].split(":")[1].split(",")]
|
assert 'Operation: new =' in lines[2]
|
||||||
assert 'Operation' in lines[2]
|
assert 'Test: divisible by' in lines[3]
|
||||||
|
assert 'If true: throw to' in lines[4]
|
||||||
|
assert 'If false: throw to' in lines[5]
|
||||||
|
|
||||||
|
items[i] = [int(x.strip()) for x in lines[1].split(":")[1].split(",")]
|
||||||
op = eval("lambda old: " + lines[2].split("=")[1])
|
op = eval("lambda old: " + lines[2].split("=")[1])
|
||||||
assert 'divisible by' in lines[3]
|
|
||||||
divisor = int(lines[3].split()[-1])
|
divisor = int(lines[3].split()[-1])
|
||||||
assert 'true: throw' in lines[4]
|
|
||||||
assert 'false: throw' in lines[5]
|
|
||||||
target = [
|
target = [
|
||||||
int(lines[5].split()[-1]),
|
int(lines[5].split()[-1]),
|
||||||
int(lines[4].split()[-1]),
|
int(lines[4].split()[-1]),
|
||||||
]
|
]
|
||||||
|
monkeys.append(Monkey(items, op, divisor, target))
|
||||||
|
return monkeys, items
|
||||||
|
|
||||||
monkeys.append((items, op, divisor, target))
|
def play(monkeys, items, rounds=1, N=None):
|
||||||
return monkeys
|
throws = Counter()
|
||||||
|
for _ in range(rounds):
|
||||||
def product(it):
|
for i, m in enumerate(monkeys):
|
||||||
t = 1
|
for j, x in enumerate(items[i]):
|
||||||
for x in it:
|
if N:
|
||||||
t *= x
|
nx = m.op(x) % N
|
||||||
return t
|
else:
|
||||||
|
nx = m.op(x) // 3
|
||||||
throws = Counter()
|
trg = m.target[nx % m.divisor == 0]
|
||||||
def play(monkeys):
|
#print(f'{i}: {x} -> {nx}. throwing to {trg}')
|
||||||
N = product(m[2] for m in monkeys)
|
items[trg].append(nx)
|
||||||
for i, m in enumerate(monkeys):
|
throws[i] += len(items[i])
|
||||||
items, op, divisor, target = m
|
items[i] = []
|
||||||
for j, x in enumerate(items):
|
|
||||||
throws[i] += 1
|
|
||||||
old = x
|
|
||||||
x = op(x)
|
|
||||||
#x //= 3
|
|
||||||
x %= N
|
|
||||||
trg = target[x % divisor == 0]
|
|
||||||
#print(f'{old} -> {x}. throwing to {trg}')
|
|
||||||
monkeys[trg][0].append(x)
|
|
||||||
items[:] = []
|
|
||||||
return throws
|
return throws
|
||||||
|
|
||||||
m = parse(open("input"))
|
def show(items):
|
||||||
print(m)
|
for k in items:
|
||||||
for _ in range(10000):
|
print(k, items[k])
|
||||||
play(m)
|
|
||||||
for i, m in enumerate(m):
|
def monkeybusiness(throws):
|
||||||
print(i, m[0])
|
a, b = [x[1] for x in throws.most_common(2)]
|
||||||
a, b = sorted(throws.values())[-2:]
|
return a*b
|
||||||
print(a*b)
|
|
||||||
|
def lcm(ints):
|
||||||
|
n = 1
|
||||||
|
for x in ints:
|
||||||
|
n *= x // math.gcd(n, x)
|
||||||
|
return n
|
||||||
|
|
||||||
|
def main():
|
||||||
|
monkeys, items = parse(open("input").read())
|
||||||
|
#print(monkeys)
|
||||||
|
show(items)
|
||||||
|
|
||||||
|
tmp = {i: list(xs) for i, xs in items.items()}
|
||||||
|
throws = play(monkeys, tmp, rounds=20)
|
||||||
|
show(tmp)
|
||||||
|
print(monkeybusiness(throws))
|
||||||
|
|
||||||
|
N = lcm(m.divisor for m in monkeys)
|
||||||
|
throws = play(monkeys, items, rounds=10000, N=N)
|
||||||
|
show(items)
|
||||||
|
print(monkeybusiness(throws))
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
Loading…
Reference in New Issue