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