From 6c0caca1e16d449525e0cd796bf8b0efa8102b72 Mon Sep 17 00:00:00 2001 From: Alfred Melch Date: Thu, 17 Dec 2020 14:00:54 +0100 Subject: [PATCH] Solve 2020/13 --- 2020/13/input | 2 ++ 2020/13/solution1.py | 22 ++++++++++++ 2020/13/solution2.py | 82 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 2020/13/input create mode 100644 2020/13/solution1.py create mode 100644 2020/13/solution2.py diff --git a/2020/13/input b/2020/13/input new file mode 100644 index 0000000..096e2cc --- /dev/null +++ b/2020/13/input @@ -0,0 +1,2 @@ +1002618 +19,x,x,x,x,x,x,x,x,41,x,x,x,37,x,x,x,x,x,367,x,x,x,x,x,x,x,x,x,x,x,x,13,x,x,x,17,x,x,x,x,x,x,x,x,x,x,x,29,x,373,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,23 diff --git a/2020/13/solution1.py b/2020/13/solution1.py new file mode 100644 index 0000000..c6edf97 --- /dev/null +++ b/2020/13/solution1.py @@ -0,0 +1,22 @@ +import re + +with open('input', 'r') as f: + arrival = int(f.readline()) + buses = list(map(int, re.findall(r'[0-9]+', f.readline().strip()))) + +earliest = None +earliest_bus = None + +print(f'{arrival=}') + +for bus in buses: + wait = bus - arrival % bus + wait = 0 if wait == bus else wait + if earliest is None or wait < earliest: + earliest = wait + earliest_bus = bus + print(bus, wait) + +print(f'{earliest=} {earliest_bus=}') +print('Solution') +print(earliest * earliest_bus) diff --git a/2020/13/solution2.py b/2020/13/solution2.py new file mode 100644 index 0000000..deaf66f --- /dev/null +++ b/2020/13/solution2.py @@ -0,0 +1,82 @@ +"""Solution to 2020/13 part2 + +Declarations: +t: timestamp +bus_id, bus: used as slope (a) in the linear function + observation: bus_ids are distinct prime numbers +offset: postion of the bus in the list + t + offset = arrival of bus +normalized_offset: used so f(0) is a correct (non-negative) solution + = -offset % bus_id + used as intercept (b) in linear function +bus_solution: solutions for y in the scope of one bus. +solution: smallest y that is a solution to all linear functions + +Functions: +- The solutions per bus. linear (y=a*x+b) +- t = bus_id * x + normalized_offset +- x: natural numbers. xth solution (time of arrival - index) +- y: solutions for t in the scope of one bus. t + delta = arrival of bus + +Combining two functions: +- Given y = x0 * a0 + b0 +- Given y = x1 * a1 + b1 +- x0 * a0 + b0 = x1 * a1 + b1 +- x1 = (x0 * a0 + b0 - b1) / a1 +- Remember: x0 and x1 have to be whole numbers +- Find linear function x0 = n * a + b that describes the possible solutions +- Let x0 be in linear function x0 = n * a + b +- x1 = ((n * a + b) * a0 + b0 - b1) / a1 +- x1 = (n * a * a0 + a0 * b + b0 -b1) / a1 +- x1 = (n * a * a0) / a1 + (a0 * b + b0 - b1) / a1 +- For x1 to be a whole number: + - (n * a * a0) needs to be divisible by a1 + - since a's prime factors are distinct from a1 set a = a1 + - a0 * b + b0 - b1 needs to be divisible by a1 + - find b by brute force (b = magic_number) +- => x0 = n * a1 + magic_number +- Apply to y = x0 * a0 + b0 +- y = (n * a1 + magic_number) * a0 + b0 +- y = n * (a0 * a1) + (a0 + b0 + magic_number) + - new a = a0 * a1 + - new b = a0 + b0 + magic_number + +Apply this schema recursively (or iteratively) to all functions. Each interim +result represents a formula for all possible solutions that includes the +processed bus_ids. At last set n = 0 (in y = n * a + b) to receive the smallest +solution (earliest timestamp). +""" + +with open('input', 'r') as f: + f.readline() + buses = f.readline().strip().split(',') + +departures = [] +i = 0 +for offset, bus in enumerate(buses): + try: + bus = int(bus) + normalized_offset = -offset % bus + print(f'y = x{i} * {bus:>3} + {normalized_offset:>3} ({offset=:>2})') + departures.append((bus, normalized_offset)) + i += 1 + except ValueError: + pass +print() + +a = 1 +b = 0 +for a_cur, b_cur in departures: + magic_nr = None + i = 0 + while magic_nr is None: + if (a * i + b - b_cur) % a_cur == 0: + magic_nr = i + i += 1 + b = b + a * magic_nr + a = a * a_cur + print(f'y = n * {a} + {b} | {magic_nr=}') +print() + +print('Solution:') +print(b)