from typing import Iterator, NamedTuple, TypeAlias, TypeVar

class Coord2D(NamedTuple):
    x: int
    y: int
    def __add__(self, other: Union[Coord2D, tuple[int, int], int]) -> Coord2D: ...
    def __sub__(self, other: Union[Coord2D, tuple[int, int], int]) -> Coord2D: ...

class Coord3D(NamedTuple):
    x: int
    y: int
    z: int
    def __add__(self, other: Union[Coord3D, tuple[int, int, int], int]) -> Coord3D: ...
    def __sub__(self, other: Union[Coord3D, tuple[int, int, int], int]) -> Coord3D: ...

def manhattan_2d(a: _Coord2D, b: _Coord2D) -> int: ...
def manhattan_3d(a: _Coord3D, b: _Coord3D) -> int: ...
def is_within_2d(coord: _Coord2D, corner1: _Coord2D, corner2: _Coord2D) -> bool: ...
def is_within_3d(coord: _Coord3D, corner1: _Coord3D, corner2: _Coord3D) -> bool: ...
def neighbors_2d(coord: _Coord2D) -> list[Coord2D]: ...
def bounded_neighbors_2d(coord: _Coord2D, corner1: _Coord2D, corner2: _Coord2D) -> list[Coord2D]: ...
def neighbors_full_2d(coord: _Coord2D) -> list[Coord2D]: ...
def bounded_neighbors_full_2d(coord: _Coord2D, corner1: _Coord2D, corner2: _Coord2D) -> list[Coord2D]: ...
def neighbors_3d(coord: _Coord3D) -> list[Coord3D]: ...
def bounded_neighbors_3d(coord: _Coord3D, corner1: _Coord3D, corner2: _Coord3D) -> list[Coord3D]: ...
def neighbors_edge_3d(coord: _Coord3D) -> list[Coord3D]: ...
def bounded_neighbors_edge_3d(coord: _Coord3D, corner1: _Coord3D, corner2: _Coord3D) -> list[Coord3D]: ...
def neighbors_full_3d(coord: _Coord3D) -> list[Coord3D]: ...
def bounded_neighbors_full_3d(coord: _Coord3D, corner1: _Coord3D, corner2: _Coord3D) -> list[Coord3D]: ...
T = TypeVar('T')
MutableGrid2D: TypeAlias
Grid2D: TypeAlias
MutableGrid3D: TypeAlias
Grid3D: TypeAlias

def create_grid_2d(size: Union[_Coord2D, Grid2D[T]], default: T) -> Grid2D[T]: ...
def create_grid_3d(size: Union[_Coord3D, Grid3D[T]], default: T) -> Grid3D[T]: ...
def width_2d(grid: Grid2D[T]) -> int: ...
def height_2d(grid: Grid2D[T]) -> int: ...
def width_3d(grid: Grid3D[T]) -> int: ...
def height_3d(grid: Grid3D[T]) -> int: ...
def depth_3d(grid: Grid3D[T]) -> int: ...
def dimensions_2d(grid: Grid2D[T]) -> Coord2D: ...
def dimensions_3d(grid: Grid3D[T]) -> Coord3D: ...
def boundaries_2d(grid: Grid2D[T]) -> Coord2D: ...
def boundaries_3d(grid: Grid3D[T]) -> Coord3D: ...
def set_element_2d(grid: MutableGrid2D[T], pos: _Coord2D, value: T) -> None: ...
def get_element_2d(grid: Grid2D[T], pos: _Coord2D) -> T: ...
def set_element_3d(grid: MutableGrid3D[T], pos: _Coord3D, value: T) -> None: ...
def get_element_3d(grid: Grid3D[T], pos: _Coord3D) -> T: ...
def iter_grid_2d(grid: Grid2D[T]) -> Iterator[tuple[Coord2D, T]]: ...
def iter_grid_3d(grid: Grid3D[T]) -> Iterator[tuple[Coord3D, T]]: ...
Coord = Coord2D
Grid: TypeAlias
MutableGrid: TypeAlias
manhattan = manhattan_2d
is_within = is_within_2d
neighbors = neighbors_2d
bounded_neighbors = bounded_neighbors_2d
neighbors_full = neighbors_full_2d
bounded_neighbors_full = bounded_neighbors_full_2d
create_grid = create_grid_2d
width = width_2d
height = height_2d
dimensions = dimensions_2d
boundaries = boundaries_2d
set_element = set_element_2d
get_element = get_element_2d
iter_grid = iter_grid_2d
