# -*- 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