aoc-2020/d13/main.py

133 lines
3.3 KiB
Python
Executable File

#! /usr/bin/env python3
import sys
import math
from typing import List
from typing import Tuple
def read_file(filename: str) -> Tuple[int, List[int]]:
with open(filename) as f:
ts = int(next(f).strip())
busses = [
int(bus) if bus != "x" else -1
for bus in next(f).strip().split(",")
]
return ts, busses
def read_cli(arg: str) -> List[int]:
busses = [
int(bus) if bus != "x" else -1
for bus in arg.strip().split(",")
]
return busses
def wait_time(ts: int, bus_id: int) -> int:
return (bus_id - (ts % bus_id) % bus_id)
def part1():
ts, busses = read_file("input.txt")
min_wait = -1
min_bus_id = 0
for bus_id in busses:
if bus_id < 0:
continue
w = wait_time(ts, bus_id)
if min_wait < 0 or w < min_wait:
min_wait = w
min_bus_id = bus_id
print(f"Wait {min_wait} for bus {min_bus_id}. Answer {min_wait * min_bus_id}")
def part2(busses=None, start=0):
if busses is None:
_, busses = read_file("input.txt")
# busses = [7, 13, -1, -1, 59, -1, 31, 19]
t = start
# t = 100000000000000
# t = t - (t%7)
# if t%7 != 0:
# print("Not starting with multiple of 7")
# return
while True:
# print(f"Checking time {t}")
for i, bus_id in enumerate(busses):
if bus_id < 0:
continue
if i == 0:
w = t % bus_id
else:
w = wait_time(t, bus_id)
# print(f"Wait for bus {bus_id} is {w} expect {i}")
if w != i:
if i > 0:
t += busses[0]
else:
t += 1
break
else:
print(f"All busses match for time {t}")
break
def part2_calc(busses=None, start=0):
if busses is None:
_, busses = read_file("input.txt")
# busses = [7, 13, -1, -1, 59, -1, 31, 19]
t = start
last_index = 0
product = -1
while True:
print(f"Checking time {t}")
for i, bus_id in enumerate(busses[last_index:], last_index):
if bus_id < 0:
continue
if i == 0:
w = t % bus_id
else:
w = wait_time(t, bus_id)
print(f"Wait for bus {bus_id} is {w} expect {i}")
if w == i % bus_id:
last_index = i+1
if product < 0:
product = bus_id
else:
product = product * bus_id
print(f"New index {last_index}, new product {product}")
else:
if i > 0:
t += product
else:
t += 1
break
else:
print(f"All busses match for time {t}")
break
if __name__ == "__main__":
if len(sys.argv) == 1:
part1()
part2_calc()
else:
busses = read_cli(sys.argv[1])
b1, b2 = busses[0], busses[1]
t = b1 * math.floor(b2/b1)
print(f"Maybe t = {t}")
start = 0
if len(sys.argv) > 2:
start = int(sys.argv[2])
print("brute")
part2(busses, start)
print("")
print("calc")
part2_calc(busses, start)