use std::ops::{Add, AddAssign, DivAssign, Sub, SubAssign}; use num::*; pub mod strings; pub use advent_of_code_macros::*; pub type Table = Vec>; pub fn matrix(zero: bool, diag: bool, non_diag: bool) -> Vec<(i32, i32)> { const MIN: i32 = -1; const MAX: i32 = 1; let mut d = Vec::new(); for i in MIN..=MAX { for j in MIN..=MAX { let ia = i.abs(); let ja = j.abs(); if zero && i == 0 && j == 0 { d.push((i, j)); } if diag && ia == 1 && ja == 1 { d.push((i, j)); } if non_diag && ia != ja && ia + ja == 1 { d.push((i, j)); } } } 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; let mut length = 0; loop { if num < divider { return length + 1; } num /= divider; length += 1; } }