2023: d13: ex1: add solution

This commit is contained in:
Bruno BELANYI 2023-12-13 10:08:35 +00:00
parent 7349222bee
commit 48175ec659

84
2023/d13/ex1/ex1.py Executable file
View file

@ -0,0 +1,84 @@
#!/usr/bin/env python
import sys
from typing import NamedTuple, Optional
class Point(NamedTuple):
x: int
y: int
class Grid(NamedTuple):
points: set[Point]
lines: int
rows: int
def solve(input: str) -> int:
def parse_grid(grid: list[str]) -> Grid:
points: set[Point] = set()
for x, line in enumerate(grid):
for y, c in enumerate(line):
if c != "#":
continue
points.add(Point(x, y))
return Grid(points, len(grid), len(grid[0]))
def parse(input: str) -> list[Grid]:
return [parse_grid(grid.splitlines()) for grid in input.split("\n\n")]
def reflect_vertical(grid: Grid) -> Optional[int]:
def try_row(row: int) -> bool:
for y in range(min(row, grid.rows - row)):
for x in range(grid.lines):
left = Point(x, row - y - 1) in grid.points
right = Point(x, row + y) in grid.points
if left and right:
continue
if left or right:
return False
return True
for row in range(1, grid.rows):
if try_row(row):
return row
return None
def reflect_horizontal(grid: Grid) -> Optional[int]:
def try_line(line: int) -> bool:
for x in range(min(line, grid.lines - line)):
for y in range(grid.rows):
up = Point(line - x - 1, y) in grid.points
down = Point(line + x, y) in grid.points
if up and down:
continue
if up or down:
return False
return True
for line in range(1, grid.lines):
if try_line(line):
return line
return None
def solve(grid: Grid) -> int:
if (columns := reflect_vertical(grid)) is not None:
return columns
if (rows := reflect_horizontal(grid)) is not None:
return 100 * rows
assert False # Sanity check
grids = parse(input)
return sum(map(solve, grids))
def main() -> None:
input = sys.stdin.read()
print(solve(input))
if __name__ == "__main__":
main()