45 lines
1.2 KiB
Python
45 lines
1.2 KiB
Python
|
with open("input.txt") as f:
|
||
|
lines = f.read().splitlines()
|
||
|
|
||
|
freqs = [int(line) for line in lines]
|
||
|
print("Part 1:", sum(freqs))
|
||
|
|
||
|
## what follows is a O(n log n) solution using modulos to avoid cycling manually.
|
||
|
## personally i just did it in elixir with Stream.cycle()...
|
||
|
|
||
|
from itertools import accumulate
|
||
|
sums = [0] + list(accumulate(freqs))
|
||
|
seen = set()
|
||
|
|
||
|
# check first cycle
|
||
|
for s in sums:
|
||
|
if s in seen:
|
||
|
ans2 = s
|
||
|
seen.add(s)
|
||
|
|
||
|
# check if last element is 0 (can't do mod 0)
|
||
|
tail = sums[-1]
|
||
|
if tail == 0:
|
||
|
ans2 = 0
|
||
|
|
||
|
# calculate mapping of all mods and indexes
|
||
|
sums = sums[:-1] # the last sum is part of the next iteration -- we start at 0
|
||
|
from collections import defaultdict
|
||
|
mods = defaultdict(list)
|
||
|
for i, s in enumerate(sums):
|
||
|
mods[s % tail].append((i,s))
|
||
|
|
||
|
mini, mind, minf = None, None, None
|
||
|
for m in mods.values():
|
||
|
ss = list(sorted(m, key = lambda t: t[1])) # sort by second element of tuple
|
||
|
for i in range(1,len(ss)):
|
||
|
diff = ss[i][1] - ss[i-1][1]
|
||
|
index = ss[i-1][0] if tail > 0 else ss[i][0]
|
||
|
freq = ss[i][1] if tail > 0 else ss[i-1][1]
|
||
|
if mind is None or diff < mind or (diff == mind and index < mini):
|
||
|
mini = index
|
||
|
mind = diff
|
||
|
minf = freq
|
||
|
|
||
|
ans2 = minf
|
||
|
print("Part 2:", ans2)
|