diff --git a/challenges/2024/07-bridgeRepair/README.md b/challenges/2024/07-bridgeRepair/README.md new file mode 100644 index 0000000..40a02ff --- /dev/null +++ b/challenges/2024/07-bridgeRepair/README.md @@ -0,0 +1,14 @@ +# [Day 7: Bridge Repair](https://adventofcode.com/2024/day/7) + +Part 1 is: +* greater than 450054910499 + +Before optimisation (pregenerating then testing operator combiantions using `itertools.product("*+|", length=n)`), runtime looks something like this: + +``` +Part 1: min 0.2671 seconds, max 0.2818 seconds, avg 0.2755 +Part 2: min 23.2387 seconds, max 24.8753 seconds, avg 23.8805 +``` + +It also appeared that using string concatenation as opposed to pure mathematical functions for the concatenation operator was marginally faster in Python. + diff --git a/challenges/2024/07-bridgeRepair/main.py b/challenges/2024/07-bridgeRepair/main.py new file mode 100644 index 0000000..d1fd3c2 --- /dev/null +++ b/challenges/2024/07-bridgeRepair/main.py @@ -0,0 +1,84 @@ +import sys +import itertools +from typing import Iterable +import math + + +def parse(instr: str) -> list[tuple[int, list[int]]]: + res = [] + for line in instr.splitlines(): + spa, spb = line.split(": ") + res.append( + (int(spa), list(map(int, spb.split(" ")))), + ) + return res + + +def evaluate(ns: list[int], ops: Iterable[str]): + acc = ns[0] + for i, (v, op) in enumerate(zip(ns[1:], ops)): + if op == "*": + acc *= v + elif op == "+": + acc += v + elif op == "|": + acc = (acc * (10 ** int(math.log10(v) + 1))) + v + else: + raise ValueError(f"unknown operation {op}") + return acc + + +def one(instr: str): + cases = parse(instr) + + cached_ops = {} + + n = 0 + for (target, numbers) in cases: + num_ops = len(numbers) - 1 + if num_ops not in cached_ops: + cached_ops[num_ops] = tuple(itertools.product("+*", repeat=num_ops)) + + for ops in cached_ops[num_ops]: + v = evaluate(numbers, ops) + if v == target: + n += v + break + + return n + + +def two(instr: str): + cases = parse(instr) + + cached_ops = {} + + n = 0 + for (target, numbers) in cases: + num_ops = len(numbers) - 1 + if num_ops not in cached_ops: + cached_ops[num_ops] = tuple(itertools.product("+*|", repeat=num_ops)) + + for ops in cached_ops[num_ops]: + v = evaluate(numbers, ops) + if v == target: + n += v + break + + return n + + +def _debug(*args, **kwargs): + kwargs["file"] = sys.stderr + print(*args, **kwargs) + + +if __name__ == "__main__": + if len(sys.argv) < 2 or sys.argv[1] not in ["1", "2"]: + print("Missing day argument", file=sys.stderr) + sys.exit(1) + inp = sys.stdin.read().strip() + if sys.argv[1] == "1": + print(one(inp)) + else: + print(two(inp)) diff --git a/challenges/2024/07-bridgeRepair/tests.json b/challenges/2024/07-bridgeRepair/tests.json new file mode 100644 index 0000000..7cb94e7 --- /dev/null +++ b/challenges/2024/07-bridgeRepair/tests.json @@ -0,0 +1,14 @@ +{ + "1": [ + { + "is": "3749", + "input": "190: 10 19\n3267: 81 40 27\n83: 17 5\n156: 15 6\n7290: 6 8 6 15\n161011: 16 10 13\n192: 17 8 14\n21037: 9 7 18 13\n292: 11 6 16 20\n" + } + ], + "2": [ + { + "is": "11387", + "input": "190: 10 19\n3267: 81 40 27\n83: 17 5\n156: 15 6\n7290: 6 8 6 15\n161011: 16 10 13\n192: 17 8 14\n21037: 9 7 18 13\n292: 11 6 16 20\n" + } + ] +} \ No newline at end of file diff --git a/challenges/2024/benchmarks.jsonl b/challenges/2024/benchmarks.jsonl index 3d1adfd..7e8c66a 100644 --- a/challenges/2024/benchmarks.jsonl +++ b/challenges/2024/benchmarks.jsonl @@ -10,3 +10,5 @@ {"day": 5, "part": 2, "runner": "py", "min": 0.02507805824279785, "max": 0.03197765350341797, "avg": 0.027084295749664308, "n": 100} {"day": 6, "part": 1, "runner": "py", "min": 0.05790352821350098, "max": 0.06762170791625977, "avg": 0.061776439348856606, "n": 6} {"day": 6, "part": 2, "runner": "py", "min": 15.881408452987671, "max": 17.086341857910156, "avg": 16.64130985736847, "n": 6} +{"day": 7, "part": 1, "runner": "py", "min": 0.26709485054016113, "max": 0.28178858757019043, "avg": 0.2754525661468506, "n": 5} +{"day": 7, "part": 2, "runner": "py", "min": 23.23872661590576, "max": 24.87530255317688, "avg": 23.880544805526732, "n": 5}