From 4147da1317c19fa61d6aa265e8370e63231f9207 Mon Sep 17 00:00:00 2001 From: Tom van der Lee Date: Sun, 19 Nov 2023 16:55:03 +0100 Subject: Initial commit --- aoc/datastructures.py | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 aoc/datastructures.py (limited to 'aoc/datastructures.py') diff --git a/aoc/datastructures.py b/aoc/datastructures.py new file mode 100644 index 0000000..1f141e2 --- /dev/null +++ b/aoc/datastructures.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +from collections import namedtuple +from typing import Iterator + + +class Coordinate(namedtuple("Coordinate", ["x", "y"])): + def __sub__(self, other: "Coordinate") -> "Coordinate": + return Coordinate(self.x - other.x, self.y - other.y) + + def __add__(self, other: "Coordinate") -> "Coordinate": + return Coordinate(self.x + other.x, self.y + other.y) + + def manhattan_distance(self, other: "Coordinate") -> int: + return abs(self.x - other.x) + abs(self.y - other.y) + + @property + def polarity(self) -> "Coordinate": + try: + px = abs(self.x) / self.x + except ZeroDivisionError: + px = 0 + + try: + py = abs(self.y) / self.y + except ZeroDivisionError: + py = 0 + + return Coordinate( + px, + py, + ) + + def neighbours(self, no_diagonal: bool = False) -> Iterator["Coordinate"]: + if no_diagonal: + yield self + Coordinate(-1, 0) + yield self + Coordinate(1, 0) + yield self + Coordinate(0, -1) + yield self + Coordinate(0, 1) + else: + for dy in range(self.y - 1, self.y + 2): + for dx in range(self.x - 1, self.x + 2): + if dy == self.y and dx == self.x: + continue + + yield Coordinate(dx, dy) + + +class Coordinate3(namedtuple("Coordinate3", ["x", "y", "z"])): + def __sub__(self, other: "Coordinate3") -> "Coordinate3": + return Coordinate3(self.x - other.x, self.y - other.y, self.z - other.z) + + def __add__(self, other: "Coordinate3") -> "Coordinate3": + return Coordinate3(self.x + other.x, self.y + other.y, self.z + other.z) + + def manhattan_distance(self, other: "Coordinate3") -> int: + return abs(self.x - other.x) + abs(self.y - other.y) + abs(self.z - other.z) + + @property + def polarity(self) -> "Coordinate3": + try: + px = abs(self.x) / self.x + except ZeroDivisionError: + px = 0 + + try: + py = abs(self.y) / self.y + except ZeroDivisionError: + py = 0 + + try: + pz = abs(self.z) / self.z + except ZeroDivisionError: + pz = 0 + + return Coordinate3( + px, + py, + pz, + ) + + def neighbours(self, no_diagonal: bool = False) -> Iterator["Coordinate3"]: + if no_diagonal: + yield self + Coordinate3(-1, 0, 0) + yield self + Coordinate3(1, 0, 0) + yield self + Coordinate3(0, -1, 0) + yield self + Coordinate3(0, 1, 0) + yield self + Coordinate3(0, 0, -1) + yield self + Coordinate3(0, 0, 1) + else: + for dz in range(self.z - 1, self.z + 2): + for dy in range(self.y - 1, self.y + 2): + for dx in range(self.x - 1, self.x + 2): + coordinate = Coordinate3(dx, dy, dz) + + if dy == self.y and dx == self.x and dz == self.z: + continue + + yield coordinate -- cgit v1.2.3