| 🪨 |
| DATA := $(BASE).dat | DATA := $(BASE).dat | ||||
| TEST := $(BASE).dtt | 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} | main: ${TEST} | ||||
| echo 'test': | echo 'test': | ||||
| cat ${TEST} | docker compose run --rm advent python -u ${CODE} | cat ${TEST} | docker compose run --rm advent python -u ${CODE} |
| 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))) |
| 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())) |