import itertools as it import operator as op from math import prod from typing import Any, Iterator import numpy as np import parse # pyright: ignore[reportMissingTypeStubs] from ..base import BaseSolver class Solver(BaseSolver): def solve(self, input: str) -> Iterator[Any]: positions: list[tuple[int, int]] = [] velocities: list[tuple[int, int]] = [] for line in input.splitlines(): r = parse.parse("p={x:d},{y:d} v={vx:d},{vy:d}", line) # type: ignore positions.append((r["y"], r["x"])) # type: ignore velocities.append((r["vy"], r["vx"])) # type: ignore n_rows, n_cols = 103, 101 if len(positions) < 20: n_rows, n_cols = 7, 11 n_rounds = 100 new_positions = [ ((row + v_row * n_rounds) % n_rows, (col + v_col * n_rounds) % n_cols) for (row, col), (v_row, v_col) in zip(positions, velocities, strict=True) ] midrow = n_rows // 2 midcol = n_cols // 2 yield prod( ( sum(opr(row, midrow) and opc(col, midcol) for row, col in new_positions) for opr, opc in it.product((op.gt, op.lt), repeat=2) ) ) new_positions = positions.copy() for rnd in self.progress.wrap(range(10000)): new_positions = [ ((row + v_row) % n_rows, (col + v_col) % n_cols) for (row, col), (v_row, v_col) in zip( new_positions, velocities, strict=True ) ] m = [[False for _ in range(n_cols)] for _ in range(n_rows)] for row, col in new_positions: m[row][col] = True found = False for row in m: if sum(row) <= 10: continue if any(all(row[i : i + 10]) for i in range(n_cols - 10)): if self.files: self.files.create( f"result_{rnd+1}.txt", "\n".join( "".join("#" if m[i][j] else "." for j in range(n_cols)) for i in range(n_rows) ).encode(), True, ) self.files.image(f"result_{rnd+1}.png", np.array(m)) yield rnd + 1 # found = True break if found: break