cp_library_rs/utils/
grid.rs

1//! グリッド探索の便利ツール
2
3use num::One;
4use num_traits::{WrappingAdd, WrappingSub};
5
6/// グリッドの探索
7pub trait Grid<T>
8where
9    Self: Sized,
10{
11    /// 座標`(i,j)`に上下左右で隣接する座標を取得
12    /// (グリッドサイズ`HxW`でバリデーション)
13    ///
14    /// **探索順**
15    ///
16    /// > ```text
17    /// >    2
18    /// >    ↑
19    /// > 3 ← → 1
20    /// >    ↓
21    /// >    4
22    /// > ```
23    fn get_adj_4(&self, rrange: (T, T), crange: (T, T)) -> Vec<Self>;
24    /// 座標`(i,j)`に8方向で隣接する座標を取得
25    /// (グリッドサイズ`HxW`でバリデーション)
26    ///
27    /// **探索順**
28    ///
29    /// > ```text
30    /// > 4  3  2
31    /// >   ↖↑↗
32    /// > 5 ← → 1
33    /// >   ↙↓➘
34    /// > 6  7  8
35    /// > ```
36    fn get_adj_8(&self, rrange: (T, T), crange: (T, T)) -> Vec<Self>;
37    /// 右のセルを返す
38    fn right(&self) -> (T, T);
39    /// 右上のセルを返す
40    fn upright(&self) -> (T, T);
41    /// 上のセルを返す
42    fn up(&self) -> (T, T);
43    /// 左上のセルを返す
44    fn upleft(&self) -> (T, T);
45    /// 左のセルを返す
46    fn left(&self) -> (T, T);
47    /// 左下のセルを返す
48    fn downleft(&self) -> (T, T);
49    /// 下のセルを返す
50    fn down(&self) -> (T, T);
51    /// 右下のセルを返す
52    fn downright(&self) -> (T, T);
53}
54
55impl<T> Grid<T> for (T, T)
56where
57    T: Clone + PartialOrd + WrappingAdd + WrappingSub + One,
58{
59    fn right(&self) -> (T, T) {
60        let (r, c) = self.clone();
61        (r, c.wrapping_add(&T::one()))
62    }
63    fn upright(&self) -> (T, T) {
64        let (r, c) = self.clone();
65        (r.wrapping_sub(&T::one()), c.wrapping_add(&T::one()))
66    }
67    fn up(&self) -> (T, T) {
68        let (r, c) = self.clone();
69        (r.wrapping_sub(&T::one()), c)
70    }
71    fn upleft(&self) -> (T, T) {
72        let (r, c) = self.clone();
73        (r.wrapping_sub(&T::one()), c.wrapping_sub(&T::one()))
74    }
75    fn left(&self) -> (T, T) {
76        let (r, c) = self.clone();
77        (r, c.wrapping_sub(&T::one()))
78    }
79    fn downleft(&self) -> (T, T) {
80        let (r, c) = self.clone();
81        (r.wrapping_add(&T::one()), c.wrapping_sub(&T::one()))
82    }
83    fn down(&self) -> (T, T) {
84        let (r, c) = self.clone();
85        (r.wrapping_add(&T::one()), c)
86    }
87    fn downright(&self) -> (T, T) {
88        let (r, c) = self.clone();
89        (r.wrapping_add(&T::one()), c.wrapping_add(&T::one()))
90    }
91    fn get_adj_4(&self, rrange: (T, T), crange: (T, T)) -> Vec<Self> {
92        [self.right(), self.up(), self.left(), self.down()]
93            .into_iter()
94            .filter(|(r, c)| (&rrange.0 <= r && r < &rrange.1) && (&crange.0 <= c && c < &crange.1))
95            .collect()
96    }
97    fn get_adj_8(&self, rrange: (T, T), crange: (T, T)) -> Vec<Self> {
98        [
99            self.right(),
100            self.upright(),
101            self.up(),
102            self.upleft(),
103            self.left(),
104            self.downleft(),
105            self.down(),
106            self.downright(),
107        ]
108        .into_iter()
109        .filter(|(r, c)| (&rrange.0 <= r && r < &rrange.1) && (&crange.0 <= c && c < &crange.1))
110        .collect()
111    }
112}