diff --git a/2020/day13.py b/2020/day13.py new file mode 100644 index 0000000..f6661df --- /dev/null +++ b/2020/day13.py @@ -0,0 +1,42 @@ +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()