78
day13/day13.py
Executable file
78
day13/day13.py
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import dataclasses
|
||||
import re
|
||||
from typing import Sequence, Set, Tuple
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
FOLD_RE = re.compile(r"fold along (?P<dir>[xy])=(?P<off>[0-9]+)")
|
||||
Point = Tuple[int, int]
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Fold:
|
||||
direction: str
|
||||
offset: int
|
||||
|
||||
@staticmethod
|
||||
def from_str(s: str) -> "Fold":
|
||||
match = FOLD_RE.match(s)
|
||||
assert match
|
||||
return Fold(match["dir"], int(match["off"]))
|
||||
|
||||
|
||||
class Grid:
|
||||
def __init__(self, points: Set[Point]):
|
||||
self.rows = max(y for x, y in points) + 1
|
||||
self.cols = max(x for x, y in points) + 1
|
||||
self.points = points
|
||||
|
||||
def apply_fold(self, fold: Fold):
|
||||
if fold.direction == "y":
|
||||
# Find all points that are below this line
|
||||
below = {(x, y) for x, y in self.points if y > fold.offset}
|
||||
# Find their new positions and then remove the old ones
|
||||
self.points -= below
|
||||
self.points |= {(x, self.rows - y - 1) for (x, y) in below}
|
||||
self.rows //= 2
|
||||
else:
|
||||
# Find all points that are to the right of this line
|
||||
right = {(x, y) for x, y in self.points if x > fold.offset}
|
||||
# Find their new positions and then remove the old ones
|
||||
self.points -= right
|
||||
self.points |= {(self.cols - x - 1, y) for (x, y) in right}
|
||||
self.cols //= 2
|
||||
|
||||
def display(self) -> Sequence[str]:
|
||||
grid = [["." for _ in range(self.cols)] for _ in range(self.rows)]
|
||||
for x, y in self.points:
|
||||
grid[y][x] = "#"
|
||||
return ["".join(line) for line in grid]
|
||||
|
||||
|
||||
def part1(grid: Grid, folds: Sequence[Fold]):
|
||||
grid = deepcopy(grid)
|
||||
grid.apply_fold(folds[0])
|
||||
print(len(grid.points))
|
||||
|
||||
|
||||
def part2(grid: Grid, folds: Sequence[Fold]):
|
||||
for fold in folds:
|
||||
grid.apply_fold(fold)
|
||||
print("\n".join(grid.display()))
|
||||
|
||||
|
||||
points_str, folds_str = sys.stdin.read().split("\n\n")
|
||||
points = {
|
||||
(int(a), int(b))
|
||||
for a, b in map(lambda line: line.split(","), points_str.split("\n"))
|
||||
}
|
||||
|
||||
grid = Grid(points)
|
||||
folds = [Fold.from_str(line) for line in folds_str.split("\n")]
|
||||
|
||||
print("Part 1")
|
||||
part1(grid, folds)
|
||||
print("Part 2")
|
||||
part2(grid, folds)
|
||||
Reference in New Issue
Block a user