| @@ -1 +1 @@ | |||
| 🪨 | |||
| 🌋 | |||
| @@ -14,12 +14,6 @@ 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': | |||
| @@ -29,6 +23,12 @@ clean: ${DATA} | |||
| echo 'real:' | |||
| cat ${DATA} | docker compose run --rm advent python -u ${CODE} | |||
| save: | |||
| git add . | |||
| test `git log -1 --format=%s` == `cat VERSION` \ | |||
| && git commit --amend --reuse-message=head \ | |||
| || git commit -m `cat VERSION` | |||
| ${DATA} ${TEST}: | |||
| # avoid spam in the lead up to the event | |||
| test ${DAY} -le `date +%d` || test ${YEAR} -lt `date +%Y` | |||
| @@ -0,0 +1,15 @@ | |||
| def solve(string, count): | |||
| plain = [ln for ln in string.splitlines()] | |||
| transposed = [''.join(ln) for ln in zip(*string.splitlines())] | |||
| for grid, m in [(plain, 100), (transposed, 1)]: | |||
| for idx in range(1, len(grid)): | |||
| aa, bb = '\n'.join(grid[:idx][::-1]), '\n'.join(grid[idx:]) | |||
| aa, bb = sorted([aa, bb], key=len) | |||
| aa, bb = set(enumerate(aa)), set(enumerate(bb)) | |||
| if len(aa - bb) == count: | |||
| return idx * m | |||
| strings = open(0).read().split('\n\n') | |||
| print(sum(solve(string, 0) for string in strings)) | |||
| print(sum(solve(string, 1) for string in strings)) | |||
| @@ -0,0 +1,50 @@ | |||
| def parse(string): | |||
| return { | |||
| complex(x, y): val | |||
| for y, row in enumerate(string.splitlines()) | |||
| for x, val in enumerate(row) | |||
| } | |||
| def render(grid): | |||
| xmin, *_, xmax = sorted({int(p.real) for p in grid}) | |||
| ymin, *_, ymax = sorted({int(p.imag) for p in grid}) | |||
| for y in range(ymin, ymax + 1): | |||
| for x in range(xmin, xmax + 1): | |||
| print(grid[complex(x, y)], end='') | |||
| print() | |||
| def rotate(grid, angle): | |||
| swaps_ongoing = 1 | |||
| while swaps_ongoing: | |||
| swaps_ongoing = 0 | |||
| for pos, val in grid.items(): | |||
| if val == 'O': | |||
| while grid.get(pos + angle) == '.': | |||
| pos, old = pos + angle, pos | |||
| grid[pos], grid[old] = val, '.' | |||
| swaps_ongoing += 1 | |||
| return grid | |||
| def calc_load(state): | |||
| return int(sum(height - p.imag + 1 for p, val in state.items() if val == 'O')) | |||
| text = open(0).read() | |||
| grid = parse(text) | |||
| height = max(p.imag for p in grid) | |||
| print(calc_load(rotate(grid, -1j))) | |||
| seq = [] | |||
| while True: | |||
| signature = frozenset(grid.items()) | |||
| if signature in seq: | |||
| break | |||
| seq.append(signature) | |||
| for angle in [-1j, -1, 1j, 1]: | |||
| grid = rotate(grid, angle) | |||
| prelude = seq.index(signature) | |||
| cycle_length = len(seq) - prelude | |||
| print(calc_load(dict(seq[prelude + (1_000_000_000 - prelude) % cycle_length]))) | |||