haar_lib/grid/
mod.rs

1//! グリッド
2pub mod to_graph;
3
4/// グリッド上の位置を表す。
5#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
6pub struct Position {
7    x: usize,
8    y: usize,
9    h: usize,
10    w: usize,
11}
12
13impl Position {
14    /// `(0, 0) ~ (h - 1, w - 1)`の長方形内の位置`(x, y)`を表す`Position`を返す。
15    pub fn new(x: usize, y: usize, h: usize, w: usize) -> Self {
16        Self { x, y, h, w }
17    }
18
19    /// x方向の位置
20    pub fn x(self) -> usize {
21        self.x
22    }
23
24    /// y方向の位置
25    pub fn y(self) -> usize {
26        self.y
27    }
28
29    /// `(self.x + d.dx, self.y + d.dy)`に相当する`Position`を`Some`に包んで返す。
30    ///
31    /// 移動先が`(0, 0)`から`(h - 1, w - 1)`の外部にある場合、`None`を返す。
32    pub fn mov(self, d: Dir) -> Option<Self> {
33        let x = self.x.checked_add_signed(d.dx)?;
34        let y = self.y.checked_add_signed(d.dy)?;
35
36        (x < self.h && y < self.w).then_some(Self { x, y, ..self })
37    }
38}
39
40/// 移動方向
41#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
42pub struct Dir {
43    /// x方向の移動量
44    pub dx: isize,
45    /// y方向の移動量
46    pub dy: isize,
47}
48
49impl Dir {
50    /// 移動量`(dx, dy)`の`Dir`を返す。
51    pub fn new(dx: isize, dy: isize) -> Self {
52        Self { dx, dy }
53    }
54
55    /// 左方向への1マス分の移動
56    pub const L: Dir = Dir { dx: 0, dy: -1 };
57    /// 右方向への1マス分の移動
58    pub const R: Dir = Dir { dx: 0, dy: 1 };
59    /// 上方向への1マス分の移動
60    pub const U: Dir = Dir { dx: -1, dy: 0 };
61    /// 下方向への1マス分の移動
62    pub const D: Dir = Dir { dx: 1, dy: 0 };
63    /// 上下左右4方向への1マス分の移動を格納した配列
64    pub const DIR_4: [Dir; 4] = [Self::L, Self::R, Self::U, Self::D];
65}
66
67impl std::ops::Add for Dir {
68    type Output = Self;
69    fn add(self, other: Self) -> Self {
70        Self::new(self.dx + other.dx, self.dy + other.dy)
71    }
72}
73
74/// 長方形型のマス目グリッドを扱う。
75#[derive(Clone, Debug)]
76pub struct Grid<T> {
77    grid: Vec<Vec<T>>,
78    h: usize,
79    w: usize,
80}
81
82impl<T> Grid<T> {
83    /// [`Vec<Vec<T>>`]などから[`Grid`]を構築する。
84    pub fn new(g: impl IntoIterator<Item = impl Into<Vec<T>>>) -> Option<Self> {
85        let grid: Vec<_> = g.into_iter().map(|a| a.into()).collect();
86
87        let w = grid.first().map_or(0, |a| a.len());
88
89        for a in &grid {
90            if a.len() != w {
91                return None;
92            }
93        }
94        let h = grid.len();
95
96        Some(Self { grid, h, w })
97    }
98
99    /// 位置`p`の要素への参照を返す。
100    pub fn get(&self, p: Position) -> &T {
101        &self.grid[p.x][p.y]
102    }
103
104    /// 位置`p`の要素への可変参照を返す。
105    pub fn get_mut(&mut self, p: Position) -> &mut T {
106        &mut self.grid[p.x][p.y]
107    }
108
109    /// グリッド上の位置と要素の参照のタプルへのイテレータを返す。
110    pub fn iter(&self) -> impl Iterator<Item = (Position, &T)> {
111        let (h, w) = (self.h, self.w);
112        self.grid.iter().enumerate().flat_map(move |(i, v)| {
113            v.iter()
114                .enumerate()
115                .map(move |(j, x)| (Position::new(i, j, h, w), x))
116        })
117    }
118
119    /// グリッド上の位置と要素の可変参照のタプルへのイテレータを返す。
120    pub fn iter_mut(&mut self) -> impl Iterator<Item = (Position, &mut T)> {
121        let (h, w) = (self.h, self.w);
122        self.grid.iter_mut().enumerate().flat_map(move |(i, v)| {
123            v.iter_mut()
124                .enumerate()
125                .map(move |(j, x)| (Position::new(i, j, h, w), x))
126        })
127    }
128}
129
130impl<T> From<Grid<T>> for Vec<Vec<T>> {
131    fn from(value: Grid<T>) -> Self {
132        value.grid
133    }
134}
135
136impl<T> AsRef<[Vec<T>]> for Grid<T> {
137    fn as_ref(&self) -> &[Vec<T>] {
138        &self.grid
139    }
140}