| @@ -0,0 +1 @@ | |||
| 🪨 | |||
| @@ -14,6 +14,13 @@ CODE := $(BASE).py | |||
| DATA := $(BASE).dat | |||
| TEST := $(BASE).dtt | |||
| save: | |||
| git add . | |||
| test `git log -1 --format=%s` == `cat VERSION` \ | |||
| && git commit --amend --reuse-message=head \ | |||
| || git commit -m `cat VERSION` | |||
| git log -1 | |||
| main: ${TEST} | |||
| echo 'test': | |||
| cat ${TEST} | docker compose run --rm advent python -u ${CODE} | |||
| @@ -0,0 +1,16 @@ | |||
| import itertools | |||
| def star_dist(a, b, N): | |||
| (xa, xb), (ya, yb) = map(sorted, zip(a, b)) | |||
| sx = sum(xa < x < xb for x in xs) | |||
| sy = sum(ya < y < yb for y in ys) | |||
| return (xb - xa) + (yb - ya) + (N - 1) * (sx + sy) | |||
| text = open(0).read() | |||
| ys = {i for i, ln in enumerate(text.splitlines()) if set(ln) == {'.'}} | |||
| xs = {i for i, ln in enumerate(zip(*text.splitlines())) if set(ln) == {'.'}} | |||
| stars = {(x, y) for y, row in enumerate(text.splitlines()) for x, val in enumerate(row) if val == '#'} | |||
| print(sum(star_dist(a, b, 2) for a, b in itertools.combinations(stars, 2))) | |||
| print(sum(star_dist(a, b, 1_000_000) for a, b in itertools.combinations(stars, 2))) | |||
| @@ -0,0 +1,35 @@ | |||
| import functools | |||
| import re | |||
| @functools.lru_cache(maxsize=None) | |||
| def get_combos(pattern, ns): | |||
| out = 0 | |||
| if not ns: | |||
| new = '_' * len(pattern) | |||
| if re.fullmatch(pattern, new): | |||
| out += 1 | |||
| else: | |||
| n, *ns = ns | |||
| i_max = len(pattern) - sum(ns) - len(ns) - n + 1 | |||
| for i in range(i_max): | |||
| new = '_' * i + '#' * n + '_' * (len(pattern) > i + n) | |||
| if re.fullmatch(pattern[:len(new)], new): | |||
| out += get_combos(pattern[len(new):], tuple(ns)) | |||
| return out | |||
| def combos(line, N=1): | |||
| pattern, ns = line.split() | |||
| # expand | |||
| pattern = '?'.join([pattern] * N) | |||
| ns = ','.join([ns] * N) | |||
| # parse | |||
| pattern = pattern.replace('.', '_').replace('?', '.') | |||
| ns = [int(n) for n in ns.split(',')] | |||
| return get_combos(pattern, tuple(ns)) | |||
| text = open(0).read() | |||
| print(sum(combos(line) for line in text.splitlines())) | |||
| print(sum(combos(line, 5) for line in text.splitlines())) | |||