adventofcode/src/lib.rs
2024-12-08 01:42:00 +01:00

281 Zeilen
7,6 KiB
Rust

use std::ops::{Add, AddAssign, DivAssign, Sub, SubAssign};
use num::*;
pub mod strings;
pub use advent_of_code_macros::*;
pub type Table = Vec<Vec<char>>;
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<T>
where
T: Integer,
{
pub x: T,
pub y: T,
}
impl<T: Integer> Add for Kartesian<T> {
fn add(self, rhs: Self) -> Self::Output {
Kartesian {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
type Output = Kartesian<T>;
}
impl<T: Integer + AddAssign> AddAssign for Kartesian<T> {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
}
}
impl<T: Integer> Sub for Kartesian<T> {
fn sub(self, rhs: Self) -> Self::Output {
Kartesian {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
type Output = Kartesian<T>;
}
impl<T: Integer + SubAssign> SubAssign for Kartesian<T> {
fn sub_assign(&mut self, rhs: Self) {
self.x -= rhs.x;
self.y -= rhs.y;
}
}
impl<T: Integer> Kartesian<T> {
pub const fn new(x: T, y: T) -> Self {
Self { x: x, y: y }
}
}
impl<T: Integer + CheckedAdd + Default> Kartesian<T> {
pub fn checked_add_max(self, rhs: Kartesian<T>, max: Kartesian<T>) -> Option<Kartesian<T>> {
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<T>
where
T: Integer,
{
pub x: T,
pub y: T,
pub z: T,
}
impl<T: Integer> Add for Euclidian<T> {
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<T>;
}
impl<T: Integer + AddAssign> AddAssign for Euclidian<T> {
fn add_assign(&mut self, rhs: Self) {
self.x += rhs.x;
self.y += rhs.y;
self.z += rhs.z;
}
}
impl<T: Integer> Sub for Euclidian<T> {
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<T>;
}
impl<T: Integer + SubAssign> SubAssign for Euclidian<T> {
fn sub_assign(&mut self, rhs: Self) {
self.x -= rhs.x;
self.y -= rhs.y;
self.z -= rhs.z;
}
}
impl<T: Integer> Euclidian<T> {
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<T: Signed + Integer + Zero + From<i8>>(self) -> Kartesian<T> {
const BELOW: i8 = -1;
const ON: i8 = 0;
const UPPER: i8 = 1;
Kartesian::<T> {
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<T: Integer + DivAssign + From<u32> + 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;
}
}