tipstar0125 / ahc

ahc
0 stars 0 forks source link

gridライブラリ #10

Open tipstar0125 opened 8 months ago

tipstar0125 commented 8 months ago

参考:https://atcoder.jp/contests/toyota2023summer-final/submissions/49683858

tipstar0125 commented 8 months ago
#[derive(Debug, Clone, Copy)]
pub struct Coord {
    row: usize,
    col: usize,
}

impl Coord {
    pub fn new(row: usize, col: usize) -> Self {
        Self { row, col }
    }
    pub fn in_map(&self, height: usize, width: usize) -> bool {
        self.row < height && self.col < width
    }
    pub fn to_index(&self, width: usize) -> CoordIndex {
        CoordIndex(self.row * width + self.col)
    }
}

impl std::ops::Add<CoordDiff> for Coord {
    type Output = Coord;
    fn add(self, rhs: CoordDiff) -> Self::Output {
        Coord::new(
            self.row.wrapping_add_signed(rhs.dr),
            self.col.wrapping_add_signed(rhs.dc),
        )
    }
}

pub struct CoordDiff {
    dr: isize,
    dc: isize,
}

impl CoordDiff {
    pub const fn new(dr: isize, dc: isize) -> Self {
        Self { dr, dc }
    }
}

pub const ADJACENT: [CoordDiff; 4] = [
    CoordDiff::new(!0, 0),
    CoordDiff::new(0, 1),
    CoordDiff::new(1, 0),
    CoordDiff::new(0, !0),
];

pub struct CoordIndex(pub usize);

impl CoordIndex {
    pub fn new(index: usize) -> Self {
        Self(index)
    }
    pub fn to_coord(&self, width: usize) -> Coord {
        Coord {
            row: self.0 / width,
            col: self.0 % width,
        }
    }
}

pub struct ConstMap2d<T, const W: usize, const HW: usize> {
    map: [T; HW],
}

impl<T, const W: usize, const HW: usize> ConstMap2d<T, W, HW>
where
    T: Copy,
{
    fn new(map: [T; HW]) -> Self {
        Self { map }
    }
    fn new_with(value: T) -> Self {
        Self { map: [value; HW] }
    }
}

impl<T, const W: usize, const HW: usize> ConstMap2d<T, W, HW>
where
    T: Copy + Default,
{
    fn with_default() -> Self {
        Self {
            map: [T::default(); HW],
        }
    }
}

impl<T, const W: usize, const HW: usize> std::ops::Index<Coord> for ConstMap2d<T, W, HW> {
    type Output = T;
    fn index(&self, index: Coord) -> &Self::Output {
        &self[index.to_index(W)]
    }
}
impl<T, const W: usize, const HW: usize> std::ops::Index<CoordIndex> for ConstMap2d<T, W, HW> {
    type Output = T;
    fn index(&self, index: CoordIndex) -> &Self::Output {
        unsafe { self.map.get_unchecked(index.0) }
    }
}
impl<T, const W: usize, const HW: usize> std::ops::IndexMut<Coord> for ConstMap2d<T, W, HW> {
    fn index_mut(&mut self, index: Coord) -> &mut Self::Output {
        &mut self[index.to_index(W)]
    }
}
impl<T, const W: usize, const HW: usize> std::ops::IndexMut<CoordIndex> for ConstMap2d<T, W, HW> {
    fn index_mut(&mut self, index: CoordIndex) -> &mut Self::Output {
        unsafe { self.map.get_unchecked_mut(index.0) }
    }
}