diff --git a/aoc.py b/aoc.py index 402e9a6..ee2c058 100644 --- a/aoc.py +++ b/aoc.py @@ -1,12 +1,16 @@ -import sys, os, shutil +import sys, os, shutil, time import __main__ def get_input(): + basename = __main__.__file__.replace(".py", ".txt") input_fn = os.path.join( os.path.dirname(__file__), "input", - __main__.__file__.replace(".py", ".txt") + basename ) + if not os.path.exists(input_fn): + print(f"\n{basename} not found, have you downloaded it?") + exit(1) return open(input_fn) def header(subtitle : str): @@ -18,4 +22,21 @@ def header(subtitle : str): print(f" │ {{:^{width - 5}}} │".format(title)) print(f" │ {{:^{width - 5}}} │".format(subtitle)) print(f" ╰{'─' * (width - 3)}╯") + print() + +def output(part : int, func, post=None, comment=None, args=[], kwargs={}): + print(f"⧖ Part {part}", end="", flush=True) + t0 = time.perf_counter() + result = func(*args, **kwargs) + t1 = time.perf_counter() + + print(f"\r✓ Part {part}", flush=True) + print(f" Elapsed: {(t1-t0)*1000:>10.3f} ms") + + if comment is not None: print(f" {comment}") + if post is not None: + post(result) + else: + print(f" {result}") + print() \ No newline at end of file diff --git a/day01.py b/day01.py index b9e8b70..ebcfe59 100644 --- a/day01.py +++ b/day01.py @@ -5,16 +5,8 @@ def main(): aoc.header("The Tyranny of the Rocket Equation") test() - t0 = time.perf_counter() - p1 = part1() - t1 = time.perf_counter() - print(f"Part 1:\t{p1}\t[{(t1-t0)*1000:.2f} ms]") - - t0 = time.perf_counter() - p2 = part2() - t1 = time.perf_counter() - print(f"Part 1:\t{p2}\t[{(t1-t0)*1000:.2f} ms]") - + aoc.output(1, part1) + aoc.output(2, part2) def part1(): return sum(map(get_fuel_required, map(int, aoc.get_input().readlines()))) @@ -34,7 +26,7 @@ def test(): assert get_fuel_required_recursive(1969) == 966 assert get_fuel_required_recursive(100756) == 50346 - print("All tests passed!") + print("✓ All tests passed!") @functools.lru_cache def get_fuel_required(mass : int): diff --git a/day02.py b/day02.py index 678119f..6f91da7 100644 --- a/day02.py +++ b/day02.py @@ -5,15 +5,9 @@ def main(): aoc.header("1202 Program Alarm") test() - t0 = time.perf_counter() - p1 = part1() - t1 = time.perf_counter() - print(f"Part 1:\t{p1}\t[{(t1-t0)*1000:.2f} ms]") - - t0 = time.perf_counter() - p2 = part2() - t1 = time.perf_counter() - print(f"Part 2:\t{p2}\t[{(t1-t0)*1000:.2f} ms]") + aoc.output(1, part1) + aoc.output(2, part2, comment="Nested loop") + aoc.output(2, part2_mp, comment="Multiprocessing") def test(): # part 1 @@ -27,7 +21,7 @@ def assert_becomes(input : typing.List[int], output : str): assert_becomes([2,3,0,3,99], "2,3,0,6,99") assert_becomes([2,4,4,5,99,0], "2,4,4,5,99,9801") assert_becomes([1,1,1,4,99,5,6,0,99], "30,1,1,4,2,5,6,0,99") - print("All tests passed!") + print("✓ All tests passed!") def part1(): return run(12,2) @@ -38,6 +32,17 @@ def part2(): if run(noun, verb) == 19690720: return (100*noun) + verb +def part2_mp(): + from multiprocessing import Pool + args = [(noun, verb) for noun in range(100) for verb in range(100)] + with Pool() as p: + it = p.imap(run_mp, args) + result = next(r for r in it if r[0] == 19690720) + noun,verb = result[1:] + return (100*noun) + verb + +def run_mp(t : typing.Tuple[int]): return(run(*t), *t) + def run(noun : int, verb : int): initial_memory = [int(x) for x in aoc.get_input().readline().split(",")] initial_memory[1] = noun