solved part 1 of day 14 of 2024

Dieser Commit ist enthalten in:
Sebastian Tobie 2024-12-15 13:22:03 +01:00
Ursprung 6236636fc9
Commit 49262fba4a
13 geänderte Dateien mit 639 neuen und 184 gelöschten Zeilen

14
Cargo.lock generiert
Datei anzeigen

@ -7,8 +7,10 @@ name = "advent-of-code"
version = "0.1.0"
dependencies = [
"advent-of-code-macros",
"log",
"num",
"regex",
"thousands",
]
[[package]]
@ -35,6 +37,12 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memchr"
version = "2.7.4"
@ -172,6 +180,12 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "thousands"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820"
[[package]]
name = "unicode-ident"
version = "1.0.14"

Datei anzeigen

@ -310,6 +310,8 @@ name = "advent_of_code"
[dependencies]
num="0.4.*"
log="0.4.*"
thousands="0.2.*"
[dependencies.advent-of-code-macros]
path = "macros"

15
Makefile Normale Datei
Datei anzeigen

@ -0,0 +1,15 @@
CARGO:=cargo
CARGO_OPTS:=-q
TARGET_DIR:=debug
fmt:
@$(CARGO) fmt 2>/dev/null
%: fmt
@$(CARGO) build $(CARGO_OPTS) --bin $@
@timeout --preserve-status -v 60 ./target/$(TARGET_DIR)/$@
Makefile:
exit
all: 202{3,4}-{01..25}

12
examples/2024/14.txt Normale Datei
Datei anzeigen

@ -0,0 +1,12 @@
p=0,4 v=3,-3
p=6,3 v=-1,-3
p=10,3 v=-1,2
p=2,0 v=2,-1
p=0,0 v=1,3
p=3,0 v=-2,-2
p=7,6 v=-1,-3
p=3,0 v=-1,-2
p=9,3 v=2,3
p=7,3 v=-1,2
p=2,4 v=2,-3
p=9,5 v=-3,-3

17
rustfmt.toml Normale Datei
Datei anzeigen

@ -0,0 +1,17 @@
array_width = 0
binop_separator= "Back"
brace_style="SameLineWhere"
chain_width = 240
fn_params_layout = "Tall"
force_explicit_abi = true
hard_tabs = false
imports_layout = "Vertical"
match_block_trailing_comma = true
max_width = 240
merge_derives = true
newline_style = "Unix"
remove_nested_parens = true
reorder_imports = true
reorder_modules = true
single_line_if_else_max_width = 0
tab_spaces = 4

126
src/bin/2024/14.rs Normale Datei
Datei anzeigen

@ -0,0 +1,126 @@
use advent_of_code::{
strings::{convert_to_array, parsenumber},
Kartesian, Velocity, KD,
};
#[allow(unused_imports)]
use advent_of_code_macros::{include_data, include_example};
include_data!(DATA 2024 14);
fn parse_robot(line: &str) -> (Kartesian<u32>, Velocity<u32>) {
let mut dir = KD::None;
let mut x = 0;
let mut y = 0;
let mut position = Kartesian::default();
for part in line.splitn(2, ' ') {
match part.get(0..2).unwrap_or("") {
"p=" => {
let (y, x) = part.get(2..).unwrap().split_once(',').unwrap();
position.x = parsenumber(x);
position.y = parsenumber(y);
},
"v=" => {
let (ys, xs) = part.get(2..).unwrap().split_once(',').unwrap();
x = parsenumber(xs);
y = parsenumber(ys);
dir = if xs.get(0..1).unwrap() == "-" && x != 0 {
dir.up()
} else if x > 0 {
dir.down()
} else {
dir
};
dir = if ys.get(0..1).unwrap() == "-" && y != 0 {
dir.left()
} else if x > 0 {
dir.right()
} else {
dir
};
},
_ => {},
}
}
(position, Velocity::new(x, y, dir))
}
fn get_end_start(v: u32) -> (u32, u32) {
match v % 2 {
0 => (v / 2, v / 2),
1 => ((v - 1) / 2 - 1, (v + 1) / 2),
_ => unreachable!(),
}
}
fn calc_safety(coords: Vec<Kartesian<u32>>, space: Kartesian<u32>) -> (u32, u32, u32, u32) {
let mut robots = (0, 0, 0, 0);
let (x_end, x_start) = get_end_start(space.x);
let (y_end, y_start) = get_end_start(space.y);
for robot in coords {
if robot.x <= x_end && robot.y <= y_end {
robots.0 += 1;
} else if robot.x <= x_end && robot.y >= y_start {
robots.1 += 1
} else if robot.x >= x_start && robot.y <= y_end {
robots.2 += 1
} else if robot.x >= x_start && robot.y >= y_start {
robots.3 += 1
} else {
println!("Robot outside of quarts {}:", robot);
println!("1. {}..={}:{}..={}", 0, x_end, 0, y_end);
println!("2. {}..={}:{}..={}", 0, x_end, y_start, space.y - 1);
println!("3. {}..={}:{}..={}", x_start, space.x - 1, 0, y_end);
println!("4. {}..={}:{}..={}", x_start, space.x - 1, y_start, space.y - 1);
}
}
println!("Robot in quarts: {}, {}, {}, {}", robots.0, robots.1, robots.2, robots.3);
robots
}
fn calc_final(r: (u32, u32, u32, u32)) -> u32 {
r.0 * r.1 * r.2 * r.3
}
fn main() {
const SPACE: Kartesian<u32> = Kartesian::new(103, 101);
let mut target_coords = Vec::new();
let robots = convert_to_array::<_, _, '\n'>(DATA, parse_robot);
for (mut position, velocity) in robots {
for _i in 0..100 {
position = position.wrapping_move_velocity(velocity, SPACE);
}
target_coords.push(position);
}
println!("{:?}", target_coords);
println!("Safety Factor: {}", calc_final(calc_safety(target_coords, SPACE)));
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_start_end() {
assert_eq!(get_end_start(7), (2, 4))
}
#[test]
fn test_safety() {
let positions = vec![
Kartesian { x: 5, y: 3 },
Kartesian { x: 4, y: 5 },
Kartesian { x: 0, y: 9 },
Kartesian { x: 5, y: 4 },
Kartesian { x: 6, y: 1 },
Kartesian { x: 3, y: 1 },
Kartesian { x: 0, y: 6 },
Kartesian { x: 3, y: 2 },
Kartesian { x: 2, y: 0 },
Kartesian { x: 0, y: 6 },
Kartesian { x: 5, y: 4 },
Kartesian { x: 6, y: 6 },
];
assert_eq!(calc_safety(positions, Kartesian::new(7, 11)), (1, 3, 4, 1));
}
}

Datei anzeigen

@ -3,13 +3,14 @@ use std::fmt::Display;
use super::{Kartesian, KartesianIterator};
use num::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum KartesianDirection {
#[default]
None,
TopLeft,
Top,
TopRight,
Left,
None,
Right,
BottomLeft,
Bottom,

Datei anzeigen

@ -0,0 +1,142 @@
use super::{Kartesian, KartesianDirection, KartesianIterator};
use super::{Map, Velocity};
use num::*;
use std::{fmt::Display, ops::*};
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 + Display + Copy> Display for Kartesian<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}:{}", self.x, self.y))
}
}
impl<T: Integer + Copy> Div<T> for Kartesian<T> {
type Output = Kartesian<T>;
fn div(self, rhs: T) -> Self::Output {
Kartesian {
x: self.x.div_ceil(&rhs),
y: self.y.div_ceil(&rhs),
}
}
}
impl<T: Integer + Rem> Rem for Kartesian<T> {
type Output = Self;
fn rem(self, rhs: Self) -> Self {
Kartesian { x: self.x % rhs.x, y: self.y % rhs.y }
}
}
impl<T: Integer + RemAssign> RemAssign for Kartesian<T> {
fn rem_assign(&mut self, rhs: Self) {
self.x %= rhs.x;
self.y %= rhs.y;
}
}
impl Iterator for KartesianIterator {
type Item = KartesianDirection;
fn next(&mut self) -> Option<Self::Item> {
let mut i = self.i;
if self.straight {
if i < 4 {
self.i += 1;
}
match i {
0 => return Some(KartesianDirection::Right),
1 => return Some(KartesianDirection::Bottom),
2 => return Some(KartesianDirection::Left),
3 => return Some(KartesianDirection::Top),
_ => i -= 4,
}
}
if self.none {
if i == 0 {
self.i += 1;
return Some(KartesianDirection::None);
}
i -= 1;
}
if self.diagonal {
if i < 4 {
self.i += 1;
}
match i {
0 => return Some(KartesianDirection::TopLeft),
1 => return Some(KartesianDirection::TopRight),
2 => return Some(KartesianDirection::BottomLeft),
3 => return Some(KartesianDirection::BottomRight),
_ => {},
}
}
None
}
}
impl<T: Display + Copy + Default> Display for Map<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for row in self.data.iter() {
for v in row.iter() {
v.fmt(f)?
}
for _ in row.len()..=self.maximum.y {
T::default().fmt(f)?
}
println!()
}
for _ in self.data.len()..=self.maximum.x {
for _ in 0..self.maximum.y {
T::default().fmt(f)?
}
println!()
}
Ok(())
}
}
impl<T: Integer + Display + Unsigned + Copy> Display for Velocity<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self.direction {
KartesianDirection::None => "",
KartesianDirection::TopLeft => "",
KartesianDirection::Top => "",
KartesianDirection::TopRight => "",
KartesianDirection::Left => "",
KartesianDirection::Right => "",
KartesianDirection::BottomLeft => "",
KartesianDirection::Bottom => "",
KartesianDirection::BottomRight => "",
})?;
self.speed.fmt(f)?;
Ok(())
}
}

Datei anzeigen

@ -1,14 +1,14 @@
use super::Kartesian;
/// Rust implementation of an Map. The Zeropoint is Topleft
/// The Rows in the data are not nessesaryly in the specifed length, should values be missing, then there are functions that returns
/// The Rows in the data are not nessesaryly in the specifed length, should values be missing, then there are functions that returns
#[derive(Debug, Clone)]
pub struct Map<T: Clone+Copy> {
maximum: Kartesian<usize>,
data: Vec<Vec<T>>,
pub struct Map<T: Clone + Copy> {
pub(super) maximum: Kartesian<usize>,
pub(super) data: Vec<Vec<T>>,
}
impl<T: Clone+Copy> Map<T> {
impl<T: Clone + Copy> Map<T> {
/// creates an empty Map
pub fn empty(length: usize, height: usize) -> Self {
Self {
@ -16,6 +16,7 @@ impl<T: Clone+Copy> Map<T> {
maximum: Kartesian::new(height, length),
}
}
/// returns true if coordinates are outside of bounds
#[inline]
fn outside(&self, coord: Kartesian<usize>) -> bool {
@ -25,7 +26,7 @@ impl<T: Clone+Copy> Map<T> {
/// Unsafe Version of the get or get_wrapping functions.
/// It does not check against an missing value and panics if its out of bounds.
#[inline]
pub unsafe fn get_unsafe(&self, coord: Kartesian<usize>) ->T{
pub unsafe fn get_unsafe(&self, coord: Kartesian<usize>) -> T {
if self.outside(coord) {
panic!("Coordinates out of bounds: {} >= {}", coord, self.maximum)
}
@ -33,7 +34,7 @@ impl<T: Clone+Copy> Map<T> {
}
}
impl<T: Copy +Copy+ Default> Map<T> {
impl<T: Copy + Copy + Default + PartialEq> Map<T> {
/// Returns an Option Containing the value.
/// Returns None if out of bounds or not yet set.
pub fn get(&self, coord: Kartesian<usize>) -> Option<T> {
@ -49,6 +50,29 @@ impl<T: Copy +Copy+ Default> Map<T> {
}
}
/// Replaces unset and default values with
pub fn replace_default(&mut self, new_value: T) {
for row in self.data.iter_mut() {
*row = row
.iter()
.map(|c| {
if *c == T::default() {
new_value
} else {
*c
}
})
.collect();
if row.len() < self.maximum.y {
row.resize(self.maximum.y, new_value);
}
}
if self.data.len() < self.maximum.x {
let full_row = vec![new_value; self.maximum.y];
self.data.resize(self.maximum.x, full_row);
}
}
/// Returns the value of in the map.
#[inline]
pub fn wrapping_get(&self, coord: Kartesian<usize>) -> T {
@ -63,7 +87,7 @@ impl<T: Copy +Copy+ Default> Map<T> {
}
pub fn set(&mut self, coord: Kartesian<usize>, value: T) -> T {
if coord.x >= self.maximum.x || coord.y >= self.maximum.y {
if self.outside(coord) {
panic!("Coordinates outside of bounds: {} >= {}", coord, self.maximum)
}
if self.data.len() < coord.x + 1 {
@ -99,7 +123,7 @@ impl<T: Copy +Copy+ Default> Map<T> {
}
}
impl<T: Clone+Copy> From<Vec<Vec<T>>> for Map<T> {
impl<T: Clone + Copy> From<Vec<Vec<T>>> for Map<T> {
fn from(value: Vec<Vec<T>>) -> Self {
Map {
data: value.clone(),

Datei anzeigen

@ -1,20 +1,27 @@
use log::debug;
use num::*;
use num::{traits::*, *};
use std::{
fmt::{Debug, Display},
ops::*,
ops::Rem,
};
pub mod direction;
pub mod external_traits;
pub mod map;
pub mod maximum;
mod test;
pub mod traits;
pub use direction::*;
pub use map::*;
pub use maximum::*;
pub use traits::*;
pub type KD = KartesianDirection;
pub trait ToCoords: Copy {
fn to_coords(self) -> Kartesian<usize>;
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Kartesian<T>
where
@ -24,42 +31,58 @@ where
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 ToCoords for Kartesian<u8> {
fn to_coords(self) -> Kartesian<usize> {
Kartesian { x: self.x as usize, y: self.y as usize }
}
}
impl ToCoords for Kartesian<u16> {
fn to_coords(self) -> Kartesian<usize> {
Kartesian { x: self.x as usize, y: self.y as usize }
}
}
impl ToCoords for Kartesian<u32> {
fn to_coords(self) -> Kartesian<usize> {
Kartesian { x: self.x as usize, y: self.y as usize }
}
}
impl ToCoords for Kartesian<u64> {
fn to_coords(self) -> Kartesian<usize> {
Kartesian { x: self.x as usize, y: self.y as usize }
}
}
impl ToCoords for Kartesian<u128> {
fn to_coords(self) -> Kartesian<usize> {
Kartesian { x: self.x as usize, y: self.y as usize }
}
}
impl ToCoords for Kartesian<usize> {
fn to_coords(self) -> Kartesian<usize> {
Kartesian { x: self.x, y: self.y }
}
}
fn wrap<T: Integer + Rem + MaximumValue + From<u32> + Copy + MaximumValue + Display, const FACTOR: u32>(v: T, max: T) -> T {
if v < max {
v
} else if v < max * T::from(FACTOR) {
v % max
} else {
max - (T::MAX - v)
}
}
impl Kartesian<usize> {
pub fn get_value<T: Copy>(self, map: &Vec<Vec<T>>) -> Option<T> {
if map.len() > self.x {
@ -72,7 +95,7 @@ impl Kartesian<usize> {
}
}
impl<T: Integer + Eq + Debug + CheckedAdd + CheckedSub + Default + Copy> Kartesian<T> {
impl<T: Integer + Eq + Debug + CheckedBasicMath + Default + Copy> 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) {
@ -181,32 +204,72 @@ impl<T: Integer + Eq + Debug + CheckedAdd + CheckedSub + Default + Copy> Kartesi
}
}
impl<T: Integer + Display + Copy> Display for Kartesian<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}:{}", self.x, self.y))
}
}
impl<T: Integer + Copy> Div<T> for Kartesian<T> {
type Output = Kartesian<T>;
fn div(self, rhs: T) -> Self::Output {
Kartesian {
x: self.x.div_ceil(&rhs),
y: self.y.div_ceil(&rhs),
impl<T: Integer + Unsigned + CheckedBasicMath> Kartesian<T> {
pub fn move_velocity(self, velocity: Velocity<T>, max: Kartesian<T>) -> Option<Kartesian<T>> {
if velocity.direction == KD::None {
return Some(self);
}
Some(Kartesian {
x: match velocity.direction {
KD::Left | KD::Right => self.x,
KD::TopLeft | KD::Top | KD::TopRight => match self.x.checked_sub(&velocity.speed.x) {
None => return None,
Some(x) => x,
},
KD::BottomLeft | KD::Bottom | KD::BottomRight => {
let x = self.x + velocity.speed.x;
if x >= max.x {
return None;
}
x
},
_ => unreachable!(),
},
y: match velocity.direction {
KD::Top | KD::Bottom => self.y,
KD::TopLeft | KD::Left | KD::BottomLeft => match self.y.checked_sub(&velocity.speed.y) {
None => return None,
Some(y) => y,
},
KD::TopRight | KD::Right | KD::BottomRight => {
let y = self.y + velocity.speed.y;
if y >= max.y {
return None;
}
y
},
_ => unreachable!(),
},
})
}
}
impl<T: Integer + Rem> Rem for Kartesian<T> {
type Output = Self;
fn rem(self, rhs: Self) -> Self {
Kartesian { x: self.x % rhs.x, y: self.y % rhs.y }
}
}
impl<T: Integer + RemAssign> RemAssign for Kartesian<T> {
fn rem_assign(&mut self, rhs: Self) {
self.x %= rhs.x;
self.y %= rhs.y;
impl<T: Integer + Display + Unsigned + WrappingAdd + WrappingSub + MaximumValue + From<u32> + Copy> Kartesian<T> {
pub fn wrapping_move_velocity(self, velocity: Velocity<T>, max: Kartesian<T>) -> Kartesian<T> {
Kartesian {
x: match velocity.direction {
KartesianDirection::TopLeft | KartesianDirection::Top | KartesianDirection::TopRight => {
if self.x < velocity.speed.x {
max.x - (velocity.speed.x - self.x)
} else {
self.x - velocity.speed.x
}
},
KartesianDirection::Left | KartesianDirection::None | KartesianDirection::Right => self.x,
KartesianDirection::BottomLeft | KartesianDirection::Bottom | KartesianDirection::BottomRight => (self.x + velocity.speed.x) % max.x,
},
y: match velocity.direction {
KartesianDirection::TopLeft | KartesianDirection::Left | KartesianDirection::BottomLeft => {
if self.y < velocity.speed.y {
max.y - (velocity.speed.y - self.y)
} else {
self.y - velocity.speed.y
}
},
KartesianDirection::Top | KartesianDirection::None | KartesianDirection::Bottom => self.y,
KartesianDirection::TopRight | KartesianDirection::Right | KartesianDirection::BottomRight => (self.y + velocity.speed.y) % max.y,
},
}
}
}
@ -217,42 +280,14 @@ pub struct KartesianIterator {
straight: bool,
}
impl Iterator for KartesianIterator {
type Item = KartesianDirection;
#[derive(Debug, Default, Clone, Copy)]
pub struct Velocity<T: Integer + Unsigned> {
speed: Kartesian<T>,
direction: KartesianDirection,
}
fn next(&mut self) -> Option<Self::Item> {
let mut i = self.i;
if self.straight {
if i < 4 {
self.i += 1;
}
match i {
0 => return Some(KartesianDirection::Right),
1 => return Some(KartesianDirection::Bottom),
2 => return Some(KartesianDirection::Left),
3 => return Some(KartesianDirection::Top),
_ => i -= 4,
}
}
if self.none {
if i == 0 {
self.i += 1;
return Some(KartesianDirection::None);
}
i -= 1;
}
if self.diagonal {
if i < 4 {
self.i += 1;
}
match i {
0 => return Some(KartesianDirection::TopLeft),
1 => return Some(KartesianDirection::TopRight),
2 => return Some(KartesianDirection::BottomLeft),
3 => return Some(KartesianDirection::BottomRight),
_ => {},
}
}
None
impl<T: Integer + Unsigned> Velocity<T> {
pub fn new(x: T, y: T, dir: KartesianDirection) -> Self {
Velocity { speed: Kartesian { x, y }, direction: dir }
}
}

Datei anzeigen

@ -1,87 +1,110 @@
#[cfg(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 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);
}
}
#[test]
fn 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);
}
}
#[test]
fn test_kartesian_iter() {
let test: Vec<_> = [
KartesianDirection::Right,
KartesianDirection::Top,
KartesianDirection::Left,
KartesianDirection::Bottom,
KartesianDirection::None,
KartesianDirection::TopLeft,
KartesianDirection::TopRight,
KartesianDirection::BottomLeft,
KartesianDirection::BottomRight,
]
.into();
let i: Vec<_> = KartesianDirection::iter(true, true, true).collect();
assert_eq!(i, test);
let test: Vec<_> = [
KartesianDirection::Right,
KartesianDirection::Top,
KartesianDirection::Left,
KartesianDirection::Bottom,
KartesianDirection::TopLeft,
KartesianDirection::TopRight,
KartesianDirection::BottomLeft,
KartesianDirection::BottomRight,
]
.into();
let i: Vec<_> = KartesianDirection::iter(false, true, true).collect();
assert_eq!(i, test);
}
#[test]
fn kartesian_iter() {
let test: Vec<_> = [
KartesianDirection::Right,
KartesianDirection::Top,
KartesianDirection::Left,
KartesianDirection::Bottom,
KartesianDirection::None,
KartesianDirection::TopLeft,
KartesianDirection::TopRight,
KartesianDirection::BottomLeft,
KartesianDirection::BottomRight,
]
.into();
let i: Vec<_> = KartesianDirection::iter(true, true, true).collect();
assert_eq!(i, test);
let test: Vec<_> = [
KartesianDirection::Right,
KartesianDirection::Top,
KartesianDirection::Left,
KartesianDirection::Bottom,
KartesianDirection::TopLeft,
KartesianDirection::TopRight,
KartesianDirection::BottomLeft,
KartesianDirection::BottomRight,
]
.into();
let i: Vec<_> = KartesianDirection::iter(false, true, true).collect();
assert_eq!(i, test);
}
#[test]
fn test_diff_dir() {
const START: Kartesian<u8> = Kartesian::new(1, 1);
// Top Group
assert_eq!(KartesianDirection::TopLeft, START.diff(Kartesian::new(0, 0)).1);
assert_eq!(KartesianDirection::Top, START.diff(Kartesian::new(0, 1)).1);
assert_eq!(KartesianDirection::TopRight, START.diff(Kartesian::new(0, 2)).1);
// Same Line
assert_eq!(KartesianDirection::Left, START.diff(Kartesian::new(1, 0)).1);
assert_eq!(KartesianDirection::None, START.diff(Kartesian::new(1, 1)).1);
assert_eq!(KartesianDirection::Right, START.diff(Kartesian::new(1, 2)).1);
// Below/Bottom Line
assert_eq!(KartesianDirection::BottomLeft, START.diff(Kartesian::new(2, 0)).1);
assert_eq!(KartesianDirection::Bottom, START.diff(Kartesian::new(2, 1)).1);
assert_eq!(KartesianDirection::BottomRight, START.diff(Kartesian::new(2, 2)).1);
}
#[test]
fn diff_dir() {
const START: Kartesian<u8> = Kartesian::new(1, 1);
// Top Group
assert_eq!(KartesianDirection::TopLeft, START.diff(Kartesian::new(0, 0)).1);
assert_eq!(KartesianDirection::Top, START.diff(Kartesian::new(0, 1)).1);
assert_eq!(KartesianDirection::TopRight, START.diff(Kartesian::new(0, 2)).1);
// Same Line
assert_eq!(KartesianDirection::Left, START.diff(Kartesian::new(1, 0)).1);
assert_eq!(KartesianDirection::None, START.diff(Kartesian::new(1, 1)).1);
assert_eq!(KartesianDirection::Right, START.diff(Kartesian::new(1, 2)).1);
// Below/Bottom Line
assert_eq!(KartesianDirection::BottomLeft, START.diff(Kartesian::new(2, 0)).1);
assert_eq!(KartesianDirection::Bottom, START.diff(Kartesian::new(2, 1)).1);
assert_eq!(KartesianDirection::BottomRight, START.diff(Kartesian::new(2, 2)).1);
}
#[test]
fn moving_wrapping() {
/*
let max: Kartesian<u32> = Kartesian::new(10, 10);
let mut pos = Kartesian::new(0, 0);
let velocity = Velocity::new(1, 1, KartesianDirection::BottomRight);
pos = pos.wrapping_move_velocity(velocity, max);
assert_eq!(pos, Kartesian::new(1, 1));
for _ in 1..10 {
pos = pos.wrapping_move_velocity(velocity, max);
}
assert_eq!(pos, Kartesian::new(0, 0));
*/
let max = Kartesian::<u32>::new(7, 11);
assert_eq!(Kartesian::new(2, 0).wrapping_move_velocity(Velocity::new(1, 3, KartesianDirection::TopLeft), max), Kartesian::new(1, 9));
assert_eq!(Kartesian::new(4, 2).wrapping_move_velocity(Velocity::new(3, 2, KartesianDirection::TopRight), max), Kartesian::new(1, 4))
}
#[test]
fn test_wrap() {
assert_eq!(wrap::<u32, 10>(11, 11), 0)
}

Datei anzeigen

@ -0,0 +1,43 @@
use num::*;
macro_rules! predefined_const {
($trait_name:ident, $const:ident, $t:ty) => {
impl $trait_name for $t {
const $const: $t = <$t>::$const;
}
};
}
pub trait CheckedBasicMath: CheckedAdd + CheckedSub {}
impl<T: CheckedAdd + CheckedSub> CheckedBasicMath for T {}
pub trait MaximumValue {
const MAX: Self;
}
predefined_const!(MaximumValue, MAX, u8);
predefined_const!(MaximumValue, MAX, u16);
predefined_const!(MaximumValue, MAX, u32);
predefined_const!(MaximumValue, MAX, u64);
predefined_const!(MaximumValue, MAX, u128);
predefined_const!(MaximumValue, MAX, usize);
predefined_const!(MaximumValue, MAX, i8);
predefined_const!(MaximumValue, MAX, i16);
predefined_const!(MaximumValue, MAX, i32);
predefined_const!(MaximumValue, MAX, i64);
predefined_const!(MaximumValue, MAX, i128);
predefined_const!(MaximumValue, MAX, isize);
pub trait MinimumValue {
const MIN: Self;
}
predefined_const!(MinimumValue, MIN, u8);
predefined_const!(MinimumValue, MIN, u16);
predefined_const!(MinimumValue, MIN, u32);
predefined_const!(MinimumValue, MIN, u64);
predefined_const!(MinimumValue, MIN, u128);
predefined_const!(MinimumValue, MIN, usize);
predefined_const!(MinimumValue, MIN, i8);
predefined_const!(MinimumValue, MIN, i16);
predefined_const!(MinimumValue, MIN, i32);
predefined_const!(MinimumValue, MIN, i64);
predefined_const!(MinimumValue, MIN, i128);
predefined_const!(MinimumValue, MIN, isize);

Datei anzeigen

@ -4,7 +4,7 @@ use std::ops::AddAssign;
#[inline]
pub fn char_to_num<T: Integer + From<u32>>(c: char) -> T {
match c {
'1' => T::from(1),
'1' => T::one(),
'2' => T::from(2),
'3' => T::from(3),
'4' => T::from(4),
@ -13,7 +13,8 @@ pub fn char_to_num<T: Integer + From<u32>>(c: char) -> T {
'7' => T::from(7),
'8' => T::from(8),
'9' => T::from(9),
'0' => T::from(0),
'0' => T::zero(),
'-' => T::zero(),
_ => unreachable!(),
}
}