refactored out Position
This commit is contained in:
parent
923e967056
commit
b83bb6b37a
12 changed files with 252 additions and 216 deletions
71
advent/common/position.py
Normal file
71
advent/common/position.py
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from typing import Iterator, Literal
|
||||
|
||||
|
||||
@dataclass(slots=True, frozen=True, order=True)
|
||||
class Position:
|
||||
x: int
|
||||
y: int
|
||||
|
||||
def __getitem__(self, index: Literal[0, 1]) -> int:
|
||||
match index:
|
||||
case 0: return self.x
|
||||
case 1: return self.y
|
||||
case _: raise IndexError()
|
||||
|
||||
def __iter__(self) -> Iterator[int]:
|
||||
yield self.x
|
||||
yield self.y
|
||||
|
||||
def set_x(self, x: int) -> Position:
|
||||
return Position(x, self.y)
|
||||
|
||||
def set_y(self, y: int) -> Position:
|
||||
return Position(self.x, y)
|
||||
|
||||
def __neg__(self) -> Position:
|
||||
return Position(-self.x, -self.y)
|
||||
|
||||
def __add__(self, other: Position) -> Position:
|
||||
return Position(self.x + other.x, self.y + other.y)
|
||||
|
||||
def __sub__(self, other: Position) -> Position:
|
||||
return Position(self.x - other.x, self.y - other.y)
|
||||
|
||||
def __mul__(self, factor: int) -> Position:
|
||||
return Position(self.x * factor, self.y * factor)
|
||||
|
||||
def taxicab_distance(self, other: Position | None = None) -> int:
|
||||
if other is None:
|
||||
return abs(self.x) + abs(self.y)
|
||||
else:
|
||||
return abs(self.x - other.x) + abs(self.y - other.y)
|
||||
|
||||
def right(self) -> Position:
|
||||
return Position(self.x + 1, self.y)
|
||||
|
||||
def up(self) -> Position:
|
||||
return Position(self.x, self.y - 1)
|
||||
|
||||
def left(self) -> Position:
|
||||
return Position(self.x - 1, self.y)
|
||||
|
||||
def down(self) -> Position:
|
||||
return Position(self.x, self.y + 1)
|
||||
|
||||
def unit_neighbors(self) -> Iterator[Position]:
|
||||
yield self.right()
|
||||
yield self.up()
|
||||
yield self.left()
|
||||
yield self.down()
|
||||
|
||||
def is_within(self, top_left: Position, bottom_right: Position) -> bool:
|
||||
return top_left.x <= self.x < bottom_right.x and top_left.y <= self.y < bottom_right.y
|
||||
|
||||
|
||||
ORIGIN = Position(0, 0)
|
||||
UNIT_X = Position(1, 0)
|
||||
UNIT_Y = Position(0, 1)
|
||||
UNIT_NEG_X = Position(-1, 0)
|
||||
UNIT_NEG_Y = Position(0, -1)
|
||||
Loading…
Add table
Add a link
Reference in a new issue