43 lines
1.2 KiB
Python
43 lines
1.2 KiB
Python
import math
|
|
import sys
|
|
from functools import reduce
|
|
from itertools import combinations
|
|
|
|
|
|
def main():
|
|
lines = [line.rstrip() for line in sys.stdin]
|
|
earliest = int(lines[0])
|
|
ids = map(int, filter(lambda s: s != "x", lines[1].split(",")))
|
|
|
|
# Part 1
|
|
wait_times = {i: i - (earliest % i) for i in ids}
|
|
best_id, wait = min(wait_times.items(), key=lambda item: item[1])
|
|
print("Part 1:", best_id * wait)
|
|
|
|
# Part 2
|
|
# math shit
|
|
# https://en.wikipedia.org/wiki/Chinese_remainder_theorem wtf is going on
|
|
ids = []
|
|
rems = []
|
|
for i, v in enumerate(lines[1].split(",")):
|
|
if v != "x":
|
|
# import hint: you want to use negative indices for remainders to
|
|
# use it with CRT here.
|
|
rems.append(-i)
|
|
ids.append(int(v))
|
|
# are all bus IDs co-prime?
|
|
assert all(math.gcd(a, b) == 1 for a, b in combinations(ids, 2))
|
|
# CRT
|
|
# https://www.youtube.com/watch?v=zIFehsBHB8o
|
|
N = reduce(lambda a, b: a * b, ids, 1)
|
|
x = 0
|
|
for ni, ai in zip(ids, rems):
|
|
Ni = N // ni
|
|
x += ai * Ni * pow(Ni, -1, ni)
|
|
x %= N
|
|
print("Part 2:", x)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|