aoc/src/util/index.rs
2023-11-16 23:12:26 +01:00

175 lines
3.5 KiB
Rust

#[derive(Eq, PartialEq, PartialOrd, Ord, Debug, Hash, Clone, Copy)]
pub struct Dim<I: ?Sized>(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<u8> 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<i64> 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];
}
}