133 lines
3.3 KiB
Python
133 lines
3.3 KiB
Python
|
#! /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)
|