day15 much faster
This commit is contained in:
parent
b83bb6b37a
commit
3d00f265ca
3 changed files with 145 additions and 38 deletions
|
|
@ -5,66 +5,97 @@ from typing import Iterator, Literal
|
|||
|
||||
@dataclass(slots=True, frozen=True, order=True)
|
||||
class Position:
|
||||
""" This class represents a position in 2D integer space """
|
||||
x: int
|
||||
y: int
|
||||
|
||||
@classmethod
|
||||
def splat(cls, value: int) -> Position:
|
||||
""" Creates a Position with two equal values """
|
||||
return Position(value, value)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"({self.x}, {self.y})"
|
||||
|
||||
def __getitem__(self, index: Literal[0, 1]) -> int:
|
||||
""" Gets the first or second component of this position """
|
||||
match index:
|
||||
case 0: return self.x
|
||||
case 1: return self.y
|
||||
case _: raise IndexError()
|
||||
|
||||
def __iter__(self) -> Iterator[int]:
|
||||
""" Iterates over all components of this psition """
|
||||
yield self.x
|
||||
yield self.y
|
||||
|
||||
def set_x(self, x: int) -> Position:
|
||||
""" Creates a copy of this position with x set to the new value """
|
||||
return Position(x, self.y)
|
||||
|
||||
def set_y(self, y: int) -> Position:
|
||||
""" Creates a copy of this position with y set to the new value """
|
||||
return Position(self.x, y)
|
||||
|
||||
def __neg__(self) -> Position:
|
||||
""" Creates a copy of this position with all values negated """
|
||||
return Position(-self.x, -self.y)
|
||||
|
||||
def __add__(self, other: Position) -> Position:
|
||||
""" Adds the components of these two positions """
|
||||
return Position(self.x + other.x, self.y + other.y)
|
||||
|
||||
def __sub__(self, other: Position) -> Position:
|
||||
""" Subtracts the components of these two positions """
|
||||
return Position(self.x - other.x, self.y - other.y)
|
||||
|
||||
def __mul__(self, factor: int) -> Position:
|
||||
""" Multiplies all components of this position by the given factor """
|
||||
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)
|
||||
""" Returns the neighboring position to the right """
|
||||
return self + UNIT_X
|
||||
|
||||
def up(self) -> Position:
|
||||
return Position(self.x, self.y - 1)
|
||||
""" Returns the neighboring position above """
|
||||
return self + UNIT_NEG_Y
|
||||
|
||||
def left(self) -> Position:
|
||||
return Position(self.x - 1, self.y)
|
||||
""" Returns the neighboring position to the left """
|
||||
return self + UNIT_NEG_X
|
||||
|
||||
def down(self) -> Position:
|
||||
return Position(self.x, self.y + 1)
|
||||
""" Returns the neighboring position below """
|
||||
return self + UNIT_Y
|
||||
|
||||
def unit_neighbors(self) -> Iterator[Position]:
|
||||
""" Returns an iterator of all direct neighbors """
|
||||
yield self.right()
|
||||
yield self.up()
|
||||
yield self.left()
|
||||
yield self.down()
|
||||
|
||||
def is_within(self, top_left: Position, bottom_right: Position) -> bool:
|
||||
"""
|
||||
Checks if this point is within the rectangle spanned by the given positions.
|
||||
bottom_right is considered to be the first point outside the spanned rectangle.
|
||||
Behavior is undefined if top_left and bottom_right are not in the correct order.
|
||||
"""
|
||||
return top_left.x <= self.x < bottom_right.x and top_left.y <= self.y < bottom_right.y
|
||||
|
||||
def taxicab_distance(self, other: Position | None = None) -> int:
|
||||
"""
|
||||
If other is given returns the taxicab distance from this point to other.
|
||||
Otherwise returns the taxicab distance of this position to the Origin.
|
||||
"""
|
||||
if other is None:
|
||||
return abs(self.x) + abs(self.y)
|
||||
else:
|
||||
return abs(self.x - other.x) + abs(self.y - other.y)
|
||||
|
||||
ORIGIN = Position(0, 0)
|
||||
|
||||
ORIGIN = Position.splat(0)
|
||||
UNIT_X = Position(1, 0)
|
||||
UNIT_Y = Position(0, 1)
|
||||
UNIT_NEG_X = Position(-1, 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue