diff --git a/src/coordinate_systems/euclidian.rs b/src/coordinate_systems/euclidian.rs new file mode 100644 index 0000000..8b9911d --- /dev/null +++ b/src/coordinate_systems/euclidian.rs @@ -0,0 +1,63 @@ +use num::*; +use std::ops::*; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Euclidian +where + T: Integer, +{ + pub x: T, + pub y: T, + pub z: T, +} + +impl Add for Euclidian { + fn add(self, rhs: Self) -> Self::Output { + Euclidian { + x: self.x + rhs.x, + y: self.y + rhs.y, + z: self.z + rhs.z, + } + } + + type Output = Euclidian; +} + +impl AddAssign for Euclidian { + fn add_assign(&mut self, rhs: Self) { + self.x += rhs.x; + self.y += rhs.y; + self.z += rhs.z; + } +} + +impl Sub for Euclidian { + fn sub(self, rhs: Self) -> Self::Output { + Euclidian { + x: self.x - rhs.x, + y: self.y - rhs.y, + z: self.z - rhs.z, + } + } + + type Output = Euclidian; +} + +impl SubAssign for Euclidian { + fn sub_assign(&mut self, rhs: Self) { + self.x -= rhs.x; + self.y -= rhs.y; + self.z -= rhs.z; + } +} + +impl Euclidian { + pub const fn new(x: T, y: T, z: T) -> Self { + Self { x: x, y: y, z: z } + } +} + +#[cfg(test)] +mod test { + use super::*; +} diff --git a/src/coordinate_systems/kartesian.rs b/src/coordinate_systems/kartesian.rs new file mode 100644 index 0000000..5323145 --- /dev/null +++ b/src/coordinate_systems/kartesian.rs @@ -0,0 +1,189 @@ +use num::*; +use std::ops::*; + +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] +pub struct Kartesian +where + T: Integer, +{ + pub x: T, + pub y: T, +} + +impl Add for Kartesian { + fn add(self, rhs: Self) -> Self::Output { + Kartesian { + x: self.x + rhs.x, + y: self.y + rhs.y, + } + } + + type Output = Kartesian; +} + +impl AddAssign for Kartesian { + fn add_assign(&mut self, rhs: Self) { + self.x += rhs.x; + self.y += rhs.y; + } +} + +impl Sub for Kartesian { + fn sub(self, rhs: Self) -> Self::Output { + Kartesian { + x: self.x - rhs.x, + y: self.y - rhs.y, + } + } + + type Output = Kartesian; +} + +impl SubAssign for Kartesian { + fn sub_assign(&mut self, rhs: Self) { + self.x -= rhs.x; + self.y -= rhs.y; + } +} + +impl Kartesian { + pub const fn new(x: T, y: T) -> Self { + Self { x: x, y: y } + } +} + +impl Kartesian { + pub fn checked_add_max(self, rhs: Kartesian, max: Kartesian) -> Option> { + let mut new = Kartesian::default(); + new.x = match self.x.checked_add(&rhs.x) { + None => return None, + Some(x) => { + if x < T::default() || x >= max.x { + return None; + } + x + } + }; + new.y = match self.y.checked_add(&rhs.y) { + None => return None, + Some(y) => { + if y < T::default() || y >= max.y { + return None; + } + y + } + }; + Some(new) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum KartesianDirection { + TopLeft, + Top, + TopRight, + Left, + None, + Right, + BottomLeft, + Bottom, + BottomRight, +} + +impl KartesianDirection { + pub fn vector>(self) -> Kartesian { + const BELOW: i8 = -1; + const ON: i8 = 0; + const UPPER: i8 = 1; + Kartesian:: { + x: match self { + Self::TopLeft | Self::Top | Self::TopRight => BELOW.into(), + Self::Left | Self::None | Self::Right => ON.into(), + Self::BottomLeft | Self::Bottom | Self::BottomRight => UPPER.into(), + }, + y: match self { + Self::TopLeft | Self::Left | Self::BottomLeft => BELOW.into(), + Self::Top | Self::None | Self::Bottom => ON.into(), + Self::TopRight | Self::Right | Self::BottomRight => UPPER.into(), + }, + } + } + + pub fn clockwise(self, diagonal: bool) -> KartesianDirection { + match (self, diagonal) { + (KartesianDirection::TopLeft, _) => Self::Top, + (KartesianDirection::Top, true) => Self::TopRight, + (KartesianDirection::Top, false) => Self::Right, + (KartesianDirection::TopRight, _) => Self::Right, + (KartesianDirection::Left, true) => Self::TopLeft, + (KartesianDirection::Left, false) => Self::Top, + (KartesianDirection::None, _) => Self::None, + (KartesianDirection::Right, true) => Self::BottomRight, + (KartesianDirection::Right, false) => Self::Bottom, + (KartesianDirection::BottomLeft, _) => Self::Left, + (KartesianDirection::Bottom, true) => Self::BottomLeft, + (KartesianDirection::Bottom, false) => Self::Left, + (KartesianDirection::BottomRight, _) => Self::Bottom, + } + } + + pub fn anticlockwise(self, diagonal: bool) -> KartesianDirection { + match (self, diagonal) { + (KartesianDirection::TopLeft, _) => Self::Left, + (KartesianDirection::Top, true) => Self::TopLeft, + (KartesianDirection::Top, false) => Self::Left, + (KartesianDirection::TopRight, _) => Self::Top, + (KartesianDirection::Left, true) => Self::BottomLeft, + (KartesianDirection::Left, false) => Self::Bottom, + (KartesianDirection::None, _) => Self::None, + (KartesianDirection::Right, true) => Self::TopRight, + (KartesianDirection::Right, false) => Self::Top, + (KartesianDirection::BottomLeft, _) => Self::Bottom, + (KartesianDirection::Bottom, true) => Self::BottomRight, + (KartesianDirection::Bottom, false) => Self::Right, + (KartesianDirection::BottomRight, _) => Self::Right, + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_clockwise() { + let mut current = KartesianDirection::Top; + let clock = [ + KartesianDirection::Top, + KartesianDirection::TopRight, + KartesianDirection::Right, + KartesianDirection::BottomRight, + KartesianDirection::Bottom, + KartesianDirection::BottomLeft, + KartesianDirection::Left, + KartesianDirection::TopLeft, + ]; + for hand in clock { + assert_eq!(current, hand); + current = current.clockwise(true); + } + } + #[test] + fn test_anticlockwise() { + let mut current = KartesianDirection::Top; + let clock = [ + KartesianDirection::Top, + KartesianDirection::TopLeft, + KartesianDirection::Left, + KartesianDirection::BottomLeft, + KartesianDirection::Bottom, + KartesianDirection::BottomRight, + KartesianDirection::Right, + KartesianDirection::TopRight, + ]; + for hand in clock { + assert_eq!(current, hand); + current = current.anticlockwise(true); + } + } +} diff --git a/src/coordinate_systems/mod.rs b/src/coordinate_systems/mod.rs new file mode 100644 index 0000000..b8aa55b --- /dev/null +++ b/src/coordinate_systems/mod.rs @@ -0,0 +1,4 @@ +mod euclidian; +mod kartesian; +pub use euclidian::*; +pub use kartesian::*; diff --git a/src/lib.rs b/src/lib.rs index 8fa93ff..477470f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,8 +2,10 @@ use std::ops::{Add, AddAssign, DivAssign, Sub, SubAssign}; use num::*; +mod coordinate_systems; pub mod strings; pub use advent_of_code_macros::*; +pub use coordinate_systems::*; pub type Table = Vec>; @@ -29,244 +31,6 @@ pub fn matrix(zero: bool, diag: bool, non_diag: bool) -> Vec<(i32, i32)> { d } -#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] -pub struct Kartesian -where - T: Integer, -{ - pub x: T, - pub y: T, -} - -impl Add for Kartesian { - fn add(self, rhs: Self) -> Self::Output { - Kartesian { - x: self.x + rhs.x, - y: self.y + rhs.y, - } - } - - type Output = Kartesian; -} - -impl AddAssign for Kartesian { - fn add_assign(&mut self, rhs: Self) { - self.x += rhs.x; - self.y += rhs.y; - } -} - -impl Sub for Kartesian { - fn sub(self, rhs: Self) -> Self::Output { - Kartesian { - x: self.x - rhs.x, - y: self.y - rhs.y, - } - } - - type Output = Kartesian; -} - -impl SubAssign for Kartesian { - fn sub_assign(&mut self, rhs: Self) { - self.x -= rhs.x; - self.y -= rhs.y; - } -} - -impl Kartesian { - pub const fn new(x: T, y: T) -> Self { - Self { x: x, y: y } - } -} - -impl Kartesian { - pub fn checked_add_max(self, rhs: Kartesian, max: Kartesian) -> Option> { - let mut new = Kartesian::default(); - new.x = match self.x.checked_add(&rhs.x) { - None => return None, - Some(x) => { - if x < T::default() || x >= max.x { - return None; - } - x - } - }; - new.y = match self.y.checked_add(&rhs.y) { - None => return None, - Some(y) => { - if y < T::default() || y >= max.y { - return None; - } - y - } - }; - Some(new) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub struct Euclidian -where - T: Integer, -{ - pub x: T, - pub y: T, - pub z: T, -} - -impl Add for Euclidian { - fn add(self, rhs: Self) -> Self::Output { - Euclidian { - x: self.x + rhs.x, - y: self.y + rhs.y, - z: self.z + rhs.z, - } - } - - type Output = Euclidian; -} - -impl AddAssign for Euclidian { - fn add_assign(&mut self, rhs: Self) { - self.x += rhs.x; - self.y += rhs.y; - self.z += rhs.z; - } -} - -impl Sub for Euclidian { - fn sub(self, rhs: Self) -> Self::Output { - Euclidian { - x: self.x - rhs.x, - y: self.y - rhs.y, - z: self.z - rhs.z, - } - } - - type Output = Euclidian; -} - -impl SubAssign for Euclidian { - fn sub_assign(&mut self, rhs: Self) { - self.x -= rhs.x; - self.y -= rhs.y; - self.z -= rhs.z; - } -} - -impl Euclidian { - pub const fn new(x: T, y: T, z: T) -> Self { - Self { x: x, y: y, z: z } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub enum KartesianDirection { - TopLeft, - Top, - TopRight, - Left, - None, - Right, - BottomLeft, - Bottom, - BottomRight, -} - -impl KartesianDirection { - pub fn vector>(self) -> Kartesian { - const BELOW: i8 = -1; - const ON: i8 = 0; - const UPPER: i8 = 1; - Kartesian:: { - x: match self { - Self::TopLeft | Self::Top | Self::TopRight => BELOW.into(), - Self::Left | Self::None | Self::Right => ON.into(), - Self::BottomLeft | Self::Bottom | Self::BottomRight => UPPER.into(), - }, - y: match self { - Self::TopLeft | Self::Left | Self::BottomLeft => BELOW.into(), - Self::Top | Self::None | Self::Bottom => ON.into(), - Self::TopRight | Self::Right | Self::BottomRight => UPPER.into(), - }, - } - } - - pub fn clockwise(self, diagonal: bool) -> KartesianDirection { - match (self, diagonal) { - (KartesianDirection::TopLeft, _) => Self::Top, - (KartesianDirection::Top, true) => Self::TopRight, - (KartesianDirection::Top, false) => Self::Right, - (KartesianDirection::TopRight, _) => Self::Right, - (KartesianDirection::Left, true) => Self::TopLeft, - (KartesianDirection::Left, false) => Self::Top, - (KartesianDirection::None, _) => Self::None, - (KartesianDirection::Right, true) => Self::BottomRight, - (KartesianDirection::Right, false) => Self::Bottom, - (KartesianDirection::BottomLeft, _) => Self::Left, - (KartesianDirection::Bottom, true) => Self::BottomLeft, - (KartesianDirection::Bottom, false) => Self::Left, - (KartesianDirection::BottomRight, _) => Self::Bottom, - } - } - - pub fn anticlockwise(self, diagonal: bool) -> KartesianDirection { - match (self, diagonal) { - (KartesianDirection::TopLeft, _) => Self::Left, - (KartesianDirection::Top, true) => Self::TopLeft, - (KartesianDirection::Top, false) => Self::Left, - (KartesianDirection::TopRight, _) => Self::Top, - (KartesianDirection::Left, true) => Self::BottomLeft, - (KartesianDirection::Left, false) => Self::Bottom, - (KartesianDirection::None, _) => Self::None, - (KartesianDirection::Right, true) => Self::TopRight, - (KartesianDirection::Right, false) => Self::Top, - (KartesianDirection::BottomLeft, _) => Self::Bottom, - (KartesianDirection::Bottom, true) => Self::BottomRight, - (KartesianDirection::Bottom, false) => Self::Right, - (KartesianDirection::BottomRight, _) => Self::Right, - } - } -} - -#[test] -fn test_clockwise() { - let mut current = KartesianDirection::Top; - let clock = [ - KartesianDirection::Top, - KartesianDirection::TopRight, - KartesianDirection::Right, - KartesianDirection::BottomRight, - KartesianDirection::Bottom, - KartesianDirection::BottomLeft, - KartesianDirection::Left, - KartesianDirection::TopLeft, - ]; - for hand in clock { - assert_eq!(current, hand); - current = current.clockwise(true); - } -} -#[test] -fn test_anticlockwise() { - let mut current = KartesianDirection::Top; - let clock = [ - KartesianDirection::Top, - KartesianDirection::TopLeft, - KartesianDirection::Left, - KartesianDirection::BottomLeft, - KartesianDirection::Bottom, - KartesianDirection::BottomRight, - KartesianDirection::Right, - KartesianDirection::TopRight, - ]; - for hand in clock { - assert_eq!(current, hand); - current = current.anticlockwise(true); - } -} - pub fn numberlength + Copy>(n: T) -> u32 { let divider = T::from(10); let mut num = n;