1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
//! グリッド探索の便利ツール
/// グリッドの探索
pub trait Grid<T>
where
Self: Sized,
{
/// usizeにおける-1
const NEG1: T;
/// 隣接する4方向(上下左右)
const ADJ4: [(T, T); 4];
/// 隣接する8方向
const ADJ8: [(T, T); 8];
/// 座標`(i,j)`に上下左右で隣接する座標を取得
/// (グリッドサイズ`HxW`でバリデーション)
///
/// **探索順**
///
/// > ```text
/// > 2
/// > ↑
/// > 3 ← → 1
/// > ↓
/// > 4
/// > ```
fn get_adj_4(&self, H: usize, W: usize) -> Vec<Self>;
/// 座標`(i,j)`に8方向で隣接する座標を取得
/// (グリッドサイズ`HxW`でバリデーション)
///
/// **探索順**
///
/// > ```text
/// > 4 3 2
/// > ↖↑↗
/// > 5 ← → 1
/// > ↙↓➘
/// > 6 7 8
/// > ```
fn get_adj_8(&self, H: usize, W: usize) -> Vec<Self>;
}
impl Grid<usize> for (usize, usize) {
const NEG1: usize = 1_usize.wrapping_neg();
const ADJ4: [(usize, usize); 4] = [(0, 1), (Self::NEG1, 0), (0, Self::NEG1), (1, 0)];
const ADJ8: [(usize, usize); 8] = [
(0, 1),
(Self::NEG1, 1),
(Self::NEG1, 0),
(Self::NEG1, Self::NEG1),
(0, Self::NEG1),
(1, Self::NEG1),
(1, 0),
(1, 1),
];
fn get_adj_4(&self, H: usize, W: usize) -> Vec<(usize, usize)> {
let mut adj = vec![];
for &(dr, dc) in &Self::ADJ4 {
let nr = self.0.wrapping_add(dr);
let nc = self.1.wrapping_add(dc);
if nr < H && nc < W {
adj.push((nr, nc));
}
}
adj
}
fn get_adj_8(&self, H: usize, W: usize) -> Vec<(usize, usize)> {
let mut adj = vec![];
for &(dr, dc) in &Self::ADJ8 {
let nr = self.0.wrapping_add(dr);
let nc = self.1.wrapping_add(dc);
if nr < H && nc < W {
adj.push((nr, nc));
}
}
adj
}
}