solved part 1 of day 14 of 2024
Dieser Commit ist enthalten in:
Ursprung
6236636fc9
Commit
49262fba4a
13 geänderte Dateien mit 639 neuen und 184 gelöschten Zeilen
14
Cargo.lock
generiert
14
Cargo.lock
generiert
|
@ -7,8 +7,10 @@ name = "advent-of-code"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"advent-of-code-macros",
|
"advent-of-code-macros",
|
||||||
|
"log",
|
||||||
"num",
|
"num",
|
||||||
"regex",
|
"regex",
|
||||||
|
"thousands",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -35,6 +37,12 @@ version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.7.4"
|
version = "2.7.4"
|
||||||
|
@ -172,6 +180,12 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thousands"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
|
|
|
@ -310,6 +310,8 @@ name = "advent_of_code"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num="0.4.*"
|
num="0.4.*"
|
||||||
|
log="0.4.*"
|
||||||
|
thousands="0.2.*"
|
||||||
|
|
||||||
[dependencies.advent-of-code-macros]
|
[dependencies.advent-of-code-macros]
|
||||||
path = "macros"
|
path = "macros"
|
||||||
|
|
15
Makefile
Normale Datei
15
Makefile
Normale Datei
|
@ -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
12
examples/2024/14.txt
Normale Datei
|
@ -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
17
rustfmt.toml
Normale Datei
|
@ -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
126
src/bin/2024/14.rs
Normale Datei
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,13 +3,14 @@ use std::fmt::Display;
|
||||||
use super::{Kartesian, KartesianIterator};
|
use super::{Kartesian, KartesianIterator};
|
||||||
use num::*;
|
use num::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
|
||||||
pub enum KartesianDirection {
|
pub enum KartesianDirection {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
TopLeft,
|
TopLeft,
|
||||||
Top,
|
Top,
|
||||||
TopRight,
|
TopRight,
|
||||||
Left,
|
Left,
|
||||||
None,
|
|
||||||
Right,
|
Right,
|
||||||
BottomLeft,
|
BottomLeft,
|
||||||
Bottom,
|
Bottom,
|
||||||
|
|
142
src/coordinate_systems/kartesian/external_traits.rs
Normale Datei
142
src/coordinate_systems/kartesian/external_traits.rs
Normale Datei
|
@ -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(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,12 +3,12 @@ use super::Kartesian;
|
||||||
/// Rust implementation of an Map. The Zeropoint is Topleft
|
/// 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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Map<T: Clone+Copy> {
|
pub struct Map<T: Clone + Copy> {
|
||||||
maximum: Kartesian<usize>,
|
pub(super) maximum: Kartesian<usize>,
|
||||||
data: Vec<Vec<T>>,
|
pub(super) data: Vec<Vec<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone+Copy> Map<T> {
|
impl<T: Clone + Copy> Map<T> {
|
||||||
/// creates an empty Map
|
/// creates an empty Map
|
||||||
pub fn empty(length: usize, height: usize) -> Self {
|
pub fn empty(length: usize, height: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -16,6 +16,7 @@ impl<T: Clone+Copy> Map<T> {
|
||||||
maximum: Kartesian::new(height, length),
|
maximum: Kartesian::new(height, length),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns true if coordinates are outside of bounds
|
/// returns true if coordinates are outside of bounds
|
||||||
#[inline]
|
#[inline]
|
||||||
fn outside(&self, coord: Kartesian<usize>) -> bool {
|
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.
|
/// Unsafe Version of the get or get_wrapping functions.
|
||||||
/// It does not check against an missing value and panics if its out of bounds.
|
/// It does not check against an missing value and panics if its out of bounds.
|
||||||
#[inline]
|
#[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) {
|
if self.outside(coord) {
|
||||||
panic!("Coordinates out of bounds: {} >= {}", coord, self.maximum)
|
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 an Option Containing the value.
|
||||||
/// Returns None if out of bounds or not yet set.
|
/// Returns None if out of bounds or not yet set.
|
||||||
pub fn get(&self, coord: Kartesian<usize>) -> Option<T> {
|
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.
|
/// Returns the value of in the map.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn wrapping_get(&self, coord: Kartesian<usize>) -> T {
|
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 {
|
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)
|
panic!("Coordinates outside of bounds: {} >= {}", coord, self.maximum)
|
||||||
}
|
}
|
||||||
if self.data.len() < coord.x + 1 {
|
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 {
|
fn from(value: Vec<Vec<T>>) -> Self {
|
||||||
Map {
|
Map {
|
||||||
data: value.clone(),
|
data: value.clone(),
|
||||||
|
|
|
@ -1,20 +1,27 @@
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use num::*;
|
use num::{traits::*, *};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
ops::*,
|
ops::Rem,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod direction;
|
pub mod direction;
|
||||||
|
pub mod external_traits;
|
||||||
pub mod map;
|
pub mod map;
|
||||||
pub mod maximum;
|
pub mod maximum;
|
||||||
mod test;
|
mod test;
|
||||||
|
pub mod traits;
|
||||||
pub use direction::*;
|
pub use direction::*;
|
||||||
pub use map::*;
|
pub use map::*;
|
||||||
pub use maximum::*;
|
pub use maximum::*;
|
||||||
|
pub use traits::*;
|
||||||
|
|
||||||
pub type KD = KartesianDirection;
|
pub type KD = KartesianDirection;
|
||||||
|
|
||||||
|
pub trait ToCoords: Copy {
|
||||||
|
fn to_coords(self) -> Kartesian<usize>;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Kartesian<T>
|
pub struct Kartesian<T>
|
||||||
where
|
where
|
||||||
|
@ -24,42 +31,58 @@ where
|
||||||
pub y: 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> {
|
impl<T: Integer> Kartesian<T> {
|
||||||
pub const fn new(x: T, y: T) -> Self {
|
pub const fn new(x: T, y: T) -> Self {
|
||||||
Self { x: x, y: y }
|
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> {
|
impl Kartesian<usize> {
|
||||||
pub fn get_value<T: Copy>(self, map: &Vec<Vec<T>>) -> Option<T> {
|
pub fn get_value<T: Copy>(self, map: &Vec<Vec<T>>) -> Option<T> {
|
||||||
if map.len() > self.x {
|
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>> {
|
pub fn checked_add_max(self, rhs: Kartesian<T>, max: Kartesian<T>) -> Option<Kartesian<T>> {
|
||||||
let mut new = Kartesian::default();
|
let mut new = Kartesian::default();
|
||||||
new.x = match self.x.checked_add(&rhs.x) {
|
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> {
|
impl<T: Integer + Unsigned + CheckedBasicMath> Kartesian<T> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
pub fn move_velocity(self, velocity: Velocity<T>, max: Kartesian<T>) -> Option<Kartesian<T>> {
|
||||||
f.write_fmt(format_args!("{}:{}", self.x, self.y))
|
if velocity.direction == KD::None {
|
||||||
}
|
return Some(self);
|
||||||
}
|
|
||||||
|
|
||||||
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),
|
|
||||||
}
|
}
|
||||||
|
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> {
|
impl<T: Integer + Display + Unsigned + WrappingAdd + WrappingSub + MaximumValue + From<u32> + Copy> Kartesian<T> {
|
||||||
type Output = Self;
|
pub fn wrapping_move_velocity(self, velocity: Velocity<T>, max: Kartesian<T>) -> Kartesian<T> {
|
||||||
fn rem(self, rhs: Self) -> Self {
|
Kartesian {
|
||||||
Kartesian { x: self.x % rhs.x, y: self.y % rhs.y }
|
x: match velocity.direction {
|
||||||
}
|
KartesianDirection::TopLeft | KartesianDirection::Top | KartesianDirection::TopRight => {
|
||||||
}
|
if self.x < velocity.speed.x {
|
||||||
impl<T: Integer + RemAssign> RemAssign for Kartesian<T> {
|
max.x - (velocity.speed.x - self.x)
|
||||||
fn rem_assign(&mut self, rhs: Self) {
|
} else {
|
||||||
self.x %= rhs.x;
|
self.x - velocity.speed.x
|
||||||
self.y %= rhs.y;
|
}
|
||||||
|
},
|
||||||
|
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,
|
straight: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for KartesianIterator {
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
type Item = KartesianDirection;
|
pub struct Velocity<T: Integer + Unsigned> {
|
||||||
|
speed: Kartesian<T>,
|
||||||
|
direction: KartesianDirection,
|
||||||
|
}
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
impl<T: Integer + Unsigned> Velocity<T> {
|
||||||
let mut i = self.i;
|
pub fn new(x: T, y: T, dir: KartesianDirection) -> Self {
|
||||||
if self.straight {
|
Velocity { speed: Kartesian { x, y }, direction: dir }
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,87 +1,110 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clockwise() {
|
fn clockwise() {
|
||||||
let mut current = KartesianDirection::Top;
|
let mut current = KartesianDirection::Top;
|
||||||
let clock = [
|
let clock = [
|
||||||
KartesianDirection::Top,
|
KartesianDirection::Top,
|
||||||
KartesianDirection::TopRight,
|
KartesianDirection::TopRight,
|
||||||
KartesianDirection::Right,
|
KartesianDirection::Right,
|
||||||
KartesianDirection::BottomRight,
|
KartesianDirection::BottomRight,
|
||||||
KartesianDirection::Bottom,
|
KartesianDirection::Bottom,
|
||||||
KartesianDirection::BottomLeft,
|
KartesianDirection::BottomLeft,
|
||||||
KartesianDirection::Left,
|
KartesianDirection::Left,
|
||||||
KartesianDirection::TopLeft,
|
KartesianDirection::TopLeft,
|
||||||
];
|
];
|
||||||
for hand in clock {
|
for hand in clock {
|
||||||
assert_eq!(current, hand);
|
assert_eq!(current, hand);
|
||||||
current = current.clockwise(true);
|
current = current.clockwise(true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[test]
|
}
|
||||||
fn test_anticlockwise() {
|
#[test]
|
||||||
let mut current = KartesianDirection::Top;
|
fn anticlockwise() {
|
||||||
let clock = [
|
let mut current = KartesianDirection::Top;
|
||||||
KartesianDirection::Top,
|
let clock = [
|
||||||
KartesianDirection::TopLeft,
|
KartesianDirection::Top,
|
||||||
KartesianDirection::Left,
|
KartesianDirection::TopLeft,
|
||||||
KartesianDirection::BottomLeft,
|
KartesianDirection::Left,
|
||||||
KartesianDirection::Bottom,
|
KartesianDirection::BottomLeft,
|
||||||
KartesianDirection::BottomRight,
|
KartesianDirection::Bottom,
|
||||||
KartesianDirection::Right,
|
KartesianDirection::BottomRight,
|
||||||
KartesianDirection::TopRight,
|
KartesianDirection::Right,
|
||||||
];
|
KartesianDirection::TopRight,
|
||||||
for hand in clock {
|
];
|
||||||
assert_eq!(current, hand);
|
for hand in clock {
|
||||||
current = current.anticlockwise(true);
|
assert_eq!(current, hand);
|
||||||
}
|
current = current.anticlockwise(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_kartesian_iter() {
|
fn kartesian_iter() {
|
||||||
let test: Vec<_> = [
|
let test: Vec<_> = [
|
||||||
KartesianDirection::Right,
|
KartesianDirection::Right,
|
||||||
KartesianDirection::Top,
|
KartesianDirection::Top,
|
||||||
KartesianDirection::Left,
|
KartesianDirection::Left,
|
||||||
KartesianDirection::Bottom,
|
KartesianDirection::Bottom,
|
||||||
KartesianDirection::None,
|
KartesianDirection::None,
|
||||||
KartesianDirection::TopLeft,
|
KartesianDirection::TopLeft,
|
||||||
KartesianDirection::TopRight,
|
KartesianDirection::TopRight,
|
||||||
KartesianDirection::BottomLeft,
|
KartesianDirection::BottomLeft,
|
||||||
KartesianDirection::BottomRight,
|
KartesianDirection::BottomRight,
|
||||||
]
|
]
|
||||||
.into();
|
.into();
|
||||||
let i: Vec<_> = KartesianDirection::iter(true, true, true).collect();
|
let i: Vec<_> = KartesianDirection::iter(true, true, true).collect();
|
||||||
assert_eq!(i, test);
|
assert_eq!(i, test);
|
||||||
let test: Vec<_> = [
|
let test: Vec<_> = [
|
||||||
KartesianDirection::Right,
|
KartesianDirection::Right,
|
||||||
KartesianDirection::Top,
|
KartesianDirection::Top,
|
||||||
KartesianDirection::Left,
|
KartesianDirection::Left,
|
||||||
KartesianDirection::Bottom,
|
KartesianDirection::Bottom,
|
||||||
KartesianDirection::TopLeft,
|
KartesianDirection::TopLeft,
|
||||||
KartesianDirection::TopRight,
|
KartesianDirection::TopRight,
|
||||||
KartesianDirection::BottomLeft,
|
KartesianDirection::BottomLeft,
|
||||||
KartesianDirection::BottomRight,
|
KartesianDirection::BottomRight,
|
||||||
]
|
]
|
||||||
.into();
|
.into();
|
||||||
let i: Vec<_> = KartesianDirection::iter(false, true, true).collect();
|
let i: Vec<_> = KartesianDirection::iter(false, true, true).collect();
|
||||||
assert_eq!(i, test);
|
assert_eq!(i, test);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_diff_dir() {
|
fn diff_dir() {
|
||||||
const START: Kartesian<u8> = Kartesian::new(1, 1);
|
const START: Kartesian<u8> = Kartesian::new(1, 1);
|
||||||
// Top Group
|
// Top Group
|
||||||
assert_eq!(KartesianDirection::TopLeft, START.diff(Kartesian::new(0, 0)).1);
|
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::Top, START.diff(Kartesian::new(0, 1)).1);
|
||||||
assert_eq!(KartesianDirection::TopRight, START.diff(Kartesian::new(0, 2)).1);
|
assert_eq!(KartesianDirection::TopRight, START.diff(Kartesian::new(0, 2)).1);
|
||||||
// Same Line
|
// Same Line
|
||||||
assert_eq!(KartesianDirection::Left, START.diff(Kartesian::new(1, 0)).1);
|
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::None, START.diff(Kartesian::new(1, 1)).1);
|
||||||
assert_eq!(KartesianDirection::Right, START.diff(Kartesian::new(1, 2)).1);
|
assert_eq!(KartesianDirection::Right, START.diff(Kartesian::new(1, 2)).1);
|
||||||
// Below/Bottom Line
|
// Below/Bottom Line
|
||||||
assert_eq!(KartesianDirection::BottomLeft, START.diff(Kartesian::new(2, 0)).1);
|
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::Bottom, START.diff(Kartesian::new(2, 1)).1);
|
||||||
assert_eq!(KartesianDirection::BottomRight, START.diff(Kartesian::new(2, 2)).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)
|
||||||
|
}
|
||||||
|
|
43
src/coordinate_systems/kartesian/traits.rs
Normale Datei
43
src/coordinate_systems/kartesian/traits.rs
Normale Datei
|
@ -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);
|
|
@ -4,7 +4,7 @@ use std::ops::AddAssign;
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn char_to_num<T: Integer + From<u32>>(c: char) -> T {
|
pub fn char_to_num<T: Integer + From<u32>>(c: char) -> T {
|
||||||
match c {
|
match c {
|
||||||
'1' => T::from(1),
|
'1' => T::one(),
|
||||||
'2' => T::from(2),
|
'2' => T::from(2),
|
||||||
'3' => T::from(3),
|
'3' => T::from(3),
|
||||||
'4' => T::from(4),
|
'4' => T::from(4),
|
||||||
|
@ -13,7 +13,8 @@ pub fn char_to_num<T: Integer + From<u32>>(c: char) -> T {
|
||||||
'7' => T::from(7),
|
'7' => T::from(7),
|
||||||
'8' => T::from(8),
|
'8' => T::from(8),
|
||||||
'9' => T::from(9),
|
'9' => T::from(9),
|
||||||
'0' => T::from(0),
|
'0' => T::zero(),
|
||||||
|
'-' => T::zero(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Laden …
Tabelle hinzufügen
In neuem Issue referenzieren