#[derive(Eq, PartialEq, PartialOrd, Ord, Debug, Hash, Clone, Copy)] pub struct Dim(pub I); pub type Ix = i64; macro_rules! impl_ix { ($($t:ident: $n:literal),+) => { $( pub type $t = Dim<[Ix; $n]>; impl From<[Ix; $n]> for $t { #[inline] fn from(value: [Ix; $n]) -> Self { Dim(value) } } #[allow(non_snake_case)] #[inline] pub fn $t() -> Dim<[Ix; $n]> { Dim([0; $n]) } )+ }; } impl_ix!( Ix2: 2, Ix3: 3 ); impl Ix2 { pub const ORIGIN: Ix2 = Dim([0, 0]); pub const UP: Ix2 = Dim([0, 1]); pub const DOWN: Ix2 = Dim([0, -1]); pub const LEFT: Ix2 = Dim([-1, 0]); pub const RIGHT: Ix2 = Dim([1, 0]); #[inline] pub fn x(&self) -> Ix { self.0[0] } #[inline] pub fn y(&self) -> Ix { self.0[1] } #[inline] pub fn clockwise(self) -> Self { Dim([-self.y(), self.x()]) } #[inline] pub fn counter_clockwise(self) -> Self { Dim([self.y(), -self.x()]) } #[inline] pub fn manhatten(&self, other: Ix2) -> i64 { (self.x() - other.x()).abs() + (self.y() - other.y()).abs() } pub fn linearize(&self, width: usize, height: usize) -> usize { self.y() as usize * height + (width - 1) } } impl From for Ix2 { #[inline] fn from(value: u8) -> Self { match value { b'U' | b'^' => Ix2::UP, b'D' | b'v' => Ix2::DOWN, b'L' | b'<' => Ix2::LEFT, b'R' | b'>' => Ix2::RIGHT, _ => panic!(""), } } } impl std::ops::Add for Ix2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { Dim([self.0[0] + rhs.0[0], self.0[1] + rhs.0[1]]) } } impl std::ops::AddAssign for Ix2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.0[0] += rhs.0[0]; self.0[1] += rhs.0[1]; } } impl std::ops::Sub for Ix2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { Dim([self.0[0] - rhs.0[0], self.0[1] - rhs.0[1]]) } } impl std::ops::SubAssign for Ix2 { #[inline] fn sub_assign(&mut self, rhs: Self) { self.0[0] -= rhs.0[0]; self.0[1] -= rhs.0[1]; } } impl std::ops::Mul for Ix2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { Dim([self.0[0] * rhs.0[0], self.0[1] * rhs.0[1]]) } } impl std::ops::Mul for Ix2 { type Output = Self; #[inline] fn mul(self, rhs: i64) -> Self::Output { Dim([self.0[0] * rhs, self.0[1] * rhs]) } } impl std::ops::Add for Ix3 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { Dim([ self.0[0] + rhs.0[0], self.0[1] + rhs.0[1], self.0[2] + rhs.0[2], ]) } } impl std::ops::AddAssign for Ix3 { #[inline] fn add_assign(&mut self, rhs: Self) { self.0[0] += rhs.0[0]; self.0[1] += rhs.0[1]; self.0[2] += rhs.0[2]; } } impl std::ops::Sub for Ix3 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { Dim([ self.0[0] - rhs.0[0], self.0[1] - rhs.0[1], self.0[2] - rhs.0[2], ]) } } impl std::ops::SubAssign for Ix3 { #[inline] fn sub_assign(&mut self, rhs: Self) { self.0[0] -= rhs.0[0]; self.0[1] -= rhs.0[1]; self.0[2] -= rhs.0[2]; } }