Created
December 5, 2021 16:24
-
-
Save jaymecd/5ad2fcb70ec984f7ee4eb8ef21b01c7f to your computer and use it in GitHub Desktop.
adventofcode 2021 05
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from __future__ import annotations | |
import sys | |
from collections import Counter | |
from pathlib import Path | |
from typing import List, Mapping, NamedTuple, Sequence | |
import enum | |
class Point(NamedTuple): | |
x: int | |
y: int | |
@classmethod | |
def create(cls, raw: str) -> Point: | |
return cls(*map(int, raw.split(","))) | |
class Board(NamedTuple): | |
points: List[Point] | |
@property | |
def overlapped_points(self) -> Mapping[Point, int]: | |
return dict(Counter(self.points)) | |
def overlapped_points_by_level(self, min_level: int): | |
return {k: v for k, v in self.overlapped_points.items() if v >= min_level} | |
class LineType(enum.Enum): | |
HORIZONTAL = enum.auto() | |
VERTICAL = enum.auto() | |
DIAGONAL = enum.auto() | |
COMPLEX = enum.auto() | |
class Line(NamedTuple): | |
p1: Point | |
p2: Point | |
@classmethod | |
def create(cls, raw: str) -> Line: | |
return cls(*map(Point.create, raw.split(" -> "))) | |
@property | |
def type(self) -> LineType: | |
if self.p1.y == self.p2.y: | |
return LineType.HORIZONTAL | |
if self.p1.x == self.p2.x: | |
return LineType.VERTICAL | |
if abs(self.p2.x - self.p1.x) == abs(self.p2.y - self.p1.y): | |
return LineType.DIAGONAL | |
return LineType.COMPLEX | |
@property | |
def supported(self) -> bool: | |
return self.horizontal or self.vertical or self.diagonal | |
@property | |
def horizontal(self) -> bool: | |
return self.type is LineType.HORIZONTAL | |
@property | |
def vertical(self) -> bool: | |
return self.type is LineType.VERTICAL | |
@property | |
def diagonal(self) -> bool: | |
return self.type is LineType.DIAGONAL | |
@property | |
def points(self) -> Sequence[Point]: | |
step_x = 1 if self.p2.x >= self.p1.x else -1 | |
step_y = 1 if self.p2.y >= self.p1.y else -1 | |
if self.horizontal: | |
return [ | |
Point(x, self.p1.y) | |
for x in range(self.p1.x, self.p2.x + step_x, step_x) | |
] | |
if self.vertical: | |
return [ | |
Point(self.p1.x, y) | |
for y in range(self.p1.y, self.p2.y + step_y, step_y) | |
] | |
if self.diagonal: | |
return [ | |
Point(self.p1.x + step_x * i, self.p1.y + step_y * i) | |
for i in range(abs(self.p2.x - self.p1.x) + 1) | |
] | |
raise NotImplementedError() | |
def parse_payload(file: Path) -> Sequence[Line]: | |
with file.open("r") as fp: | |
lines = fp.read().splitlines(False) | |
return [Line.create(line) for line in lines] | |
def render_board(board: Board, size: int): | |
overlapped_points = board.overlapped_points | |
print() | |
for row in range(size + 1): | |
for col in range(size + 1): | |
p = Point(col, row) | |
if p in overlapped_points: | |
print(overlapped_points[p], end="") | |
continue | |
print(".", end="") | |
print() | |
print() | |
def main(): | |
lines = parse_payload(Path(__file__).with_name("data.txt")) | |
lines = list(filter(lambda x: x.supported, lines)) | |
for line in lines: | |
print(f"{line} {line.type.name=}") | |
print(f"{len(lines)=}", file=sys.stderr) | |
size = max( | |
max(line.p2.x for line in lines), | |
max(line.p2.y for line in lines), | |
) | |
points = [point for line in lines for point in line.points] | |
print(f"{len(points)=}", file=sys.stderr) | |
board = Board(points) | |
# render_board(board, size) | |
dangerous_points = board.overlapped_points_by_level(2) | |
# print('dangerous_points:') | |
# pprint(dangerous_points) | |
print(f"{len(dangerous_points)=}", file=sys.stderr) | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
0,9 -> 5,9 | |
8,0 -> 0,8 | |
9,4 -> 3,4 | |
2,2 -> 2,1 | |
7,0 -> 7,4 | |
6,4 -> 2,0 | |
0,9 -> 2,9 | |
3,4 -> 1,4 | |
0,0 -> 8,8 | |
5,5 -> 8,2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment