69 lines
1.7 KiB
Python
69 lines
1.7 KiB
Python
import sys
|
|
from typing import TypeAlias
|
|
|
|
RockGrid: TypeAlias = list[list[str]]
|
|
|
|
rocks0 = [list(line) for line in sys.stdin.read().splitlines()]
|
|
|
|
|
|
def slide_rocks_top(rocks: RockGrid) -> RockGrid:
|
|
top = [0 if c == "." else 1 for c in rocks[0]]
|
|
for row in range(1, len(rocks)):
|
|
for col in range(len(rocks[0])):
|
|
match rocks[row][col]:
|
|
case "O":
|
|
if top[col] != row:
|
|
rocks[top[col]][col] = "O"
|
|
rocks[row][col] = "."
|
|
top[col] = top[col] + 1
|
|
case "#":
|
|
top[col] = row + 1
|
|
case _:
|
|
pass
|
|
return rocks
|
|
|
|
|
|
def cycle(rocks: RockGrid) -> RockGrid:
|
|
for _ in range(4):
|
|
rocks = slide_rocks_top(rocks)
|
|
rocks = [
|
|
[rocks[len(rocks) - j - 1][i] for j in range(len(rocks))]
|
|
for i in range(len(rocks[0]))
|
|
]
|
|
|
|
return rocks
|
|
|
|
|
|
rocks = slide_rocks_top([[c for c in r] for r in rocks0])
|
|
|
|
# part 1
|
|
answer_1 = sum(
|
|
(len(rocks) - i) * sum(1 for c in row if c == "O") for i, row in enumerate(rocks)
|
|
)
|
|
print(f"answer 1 is {answer_1}")
|
|
|
|
# part 2
|
|
rocks = rocks0
|
|
|
|
N = 1000000000
|
|
cycles: list[RockGrid] = []
|
|
i_cycle: int = -1
|
|
for i_cycle in range(N):
|
|
rocks = cycle(rocks)
|
|
|
|
if any(rocks == c for c in cycles):
|
|
break
|
|
|
|
cycles.append([[c for c in r] for r in rocks])
|
|
|
|
cycle_start = next(i for i in range(len(cycles)) if (rocks == cycles[i]))
|
|
cycle_length = i_cycle - cycle_start
|
|
|
|
ci = cycle_start + (N - cycle_start) % cycle_length - 1
|
|
|
|
answer_2 = sum(
|
|
(len(rocks) - i) * sum(1 for c in row if c == "O")
|
|
for i, row in enumerate(cycles[ci])
|
|
)
|
|
print(f"answer 2 is {answer_2}")
|