2021: d13: ex1: add solution
This commit is contained in:
parent
f314b9d753
commit
b9860d1f32
71
2021/d13/ex1/ex1.py
Executable file
71
2021/d13/ex1/ex1.py
Executable file
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import itertools
|
||||
import sys
|
||||
from copy import deepcopy
|
||||
from typing import Iterable, List, Tuple, cast
|
||||
|
||||
Paper = List[List[bool]]
|
||||
Instruction = Tuple[str, int]
|
||||
|
||||
|
||||
def solve(input: List[str]) -> int:
|
||||
def transpose(paper: Paper) -> Paper:
|
||||
return cast(Paper, list(zip(*paper)))
|
||||
|
||||
def fold_along_y(paper: Paper, y: int) -> Paper:
|
||||
assert not any(paper[y]) # Sanity check
|
||||
assert y >= len(paper) // 2 # Ensure that we can actually fold the paper
|
||||
|
||||
paper = deepcopy(paper)
|
||||
for i, j in zip(itertools.count(y, -1), range(y, len(paper))):
|
||||
paper[i] = [(dot_i or dot_j) for dot_i, dot_j in zip(paper[i], paper[j])]
|
||||
|
||||
paper = paper[:y]
|
||||
return paper
|
||||
|
||||
def fold_along_x(paper: Paper, x: int) -> Paper:
|
||||
return transpose(fold_along_y(transpose(paper), x))
|
||||
|
||||
def do_folds(paper: Paper, instructions: Iterable[Instruction]) -> Paper:
|
||||
for axis, n in instructions:
|
||||
if axis == "x":
|
||||
paper = fold_along_x(paper, n)
|
||||
elif axis == "y":
|
||||
paper = fold_along_y(paper, n)
|
||||
else:
|
||||
assert False # Sanity check
|
||||
|
||||
return paper
|
||||
|
||||
def parse() -> Tuple[Paper, List[Instruction]]:
|
||||
paper_part = itertools.takewhile(lambda s: s != "", input)
|
||||
fold_part = itertools.islice(
|
||||
itertools.dropwhile(lambda s: s != "", input), 1, None
|
||||
)
|
||||
|
||||
points = {(int(x), int(y)) for x, y in map(lambda s: s.split(","), paper_part)}
|
||||
folds = [
|
||||
(axis[-1], int(n)) for axis, n in map(lambda s: s.split("="), fold_part)
|
||||
]
|
||||
|
||||
width, height = max(p[0] for p in points), max(p[1] for p in points)
|
||||
|
||||
paper = [
|
||||
[(x, y) in points for x in range(width + 1)] for y in range(height + 1)
|
||||
]
|
||||
|
||||
return paper, folds
|
||||
|
||||
paper, instructions = parse()
|
||||
|
||||
return sum(itertools.chain.from_iterable(do_folds(paper, instructions[:1])))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
input = [line.strip() for line in sys.stdin.readlines()]
|
||||
print(solve(input))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in a new issue