From 3967b92757ca95a895fa5a178b9fa77533f5d72f Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Mon, 13 Dec 2021 14:25:44 +0100 Subject: [PATCH] 2021: d13: ex1: add solution --- 2021/d13/ex1/ex1.py | 71 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100755 2021/d13/ex1/ex1.py diff --git a/2021/d13/ex1/ex1.py b/2021/d13/ex1/ex1.py new file mode 100755 index 0000000..fb71b61 --- /dev/null +++ b/2021/d13/ex1/ex1.py @@ -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()