This commit is contained in:
akp 2024-12-07 12:43:13 +00:00
parent dc910fedfb
commit b2fa4b72b6
No known key found for this signature in database
GPG key ID: CF8D58F3DEB20755
4 changed files with 114 additions and 0 deletions

View file

@ -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.

View file

@ -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))

View file

@ -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"
}
]
}

View file

@ -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}