60 lines
2.0 KiB
Python
60 lines
2.0 KiB
Python
# SPDX-License-Identifier: MIT
|
|
# Copyright (c) 2021 Akumatic
|
|
#
|
|
# https://adventofcode.com/2021/day/13
|
|
|
|
class Paper:
|
|
def __init__(self, dots):
|
|
self.max_x = max(dot[0] for dot in dots) + 1
|
|
self.max_y = max(dot[1] for dot in dots) + 1
|
|
self.grid = {dot[1] * self.max_x + dot[0] for dot in dots}
|
|
|
|
def __str__(self):
|
|
return "\n".join(
|
|
["".join(["#" if x+y*self.max_x in self.grid else "." for x in range(self.max_x)]
|
|
) for y in range(self.max_y)])
|
|
|
|
def fold(self, dir: str, idx: int):
|
|
tmp = set()
|
|
for point in self.grid:
|
|
x = point % self.max_x
|
|
y = (point - x) // self.max_x
|
|
if dir == "x" and x < idx:
|
|
tmp.add(x + y * idx)
|
|
elif dir == "x" and x > idx:
|
|
tmp.add(-x + 2*idx + y * idx)
|
|
elif dir == "y" and y < idx:
|
|
tmp.add(x + y * self.max_x)
|
|
elif dir == "y" and y > idx:
|
|
tmp.add(x + (-y + 2*idx) * self.max_x)
|
|
|
|
self.grid = tmp
|
|
if dir == "x":
|
|
self.max_x = idx
|
|
else: # dir == "y"
|
|
self.max_y = idx
|
|
|
|
def read_file(filename: str = "input.txt") -> list:
|
|
with open(f"{__file__.rstrip('code.py')}{filename}", "r") as f:
|
|
lines = [line for line in f.read().strip().split("\n")]
|
|
empty = lines.index("")
|
|
dots = [(int(x[0]), int(x[1])) for x in (s.split(",") for s in lines[:empty])]
|
|
instructions = [(x[0], int(x[1])) for x in (s[11:].split("=") for s in lines[empty+1:])]
|
|
return dots, instructions
|
|
|
|
def part1(dots: list, folding_instructions: list) -> int:
|
|
paper = Paper(dots)
|
|
paper.fold(*folding_instructions[0])
|
|
return len(paper.grid)
|
|
|
|
def part2(dots: list, folding_instructions: list) -> int:
|
|
paper = Paper(dots)
|
|
for instruction in folding_instructions:
|
|
paper.fold(*instruction)
|
|
return f"\n{paper}"
|
|
|
|
if __name__ == "__main__":
|
|
vals = read_file() # vals[0] are the dots, vals[1] the folding instructions
|
|
print(f"Part 1: {part1(*vals)}")
|
|
print(f"Part 2: {part2(*vals)}")
|