Commits vergleichen
Keine gemeinsamen Commits. „bd97c2e422177eeac722c93dda444aac9e532b46“ und „4f32ca95cf9b154e91815be3c19f5a952f8eb1f0“ haben vollständig unterschiedliche Historien.
bd97c2e422
...
4f32ca95cf
13 geänderte Dateien mit 42 neuen und 785 gelöschten Zeilen
80
Cargo.lock
generiert
80
Cargo.lock
generiert
|
@ -7,7 +7,6 @@ name = "advent-of-code"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"advent-of-code-macros",
|
||||
"num",
|
||||
"regex",
|
||||
]
|
||||
|
||||
|
@ -29,91 +28,12 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
|
|
|
@ -309,7 +309,6 @@ path = "src/bin/2024/25.rs"
|
|||
name = "advent_of_code"
|
||||
|
||||
[dependencies]
|
||||
num="0.4.*"
|
||||
|
||||
[dependencies.advent-of-code-macros]
|
||||
path = "macros"
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
190: 10 19
|
||||
3267: 81 40 27
|
||||
83: 17 5
|
||||
156: 15 6
|
||||
7290: 6 8 6 15
|
||||
161011: 16 10 13
|
||||
192: 17 8 14
|
||||
21037: 9 7 18 13
|
||||
292: 11 6 16 20
|
|
@ -1,6 +1,6 @@
|
|||
use advent_of_code::strings::{get_numbers, get_string_numbers};
|
||||
#[allow(unused_imports)]
|
||||
use advent_of_code::{include_data, include_example};
|
||||
use advent_of_code_macros::{include_data, include_example};
|
||||
|
||||
include_data!(DATAa 2023 01a);
|
||||
include_data!(DATAb 2023 01b);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use advent_of_code::strings::parsenumber;
|
||||
#[allow(unused_imports)]
|
||||
use advent_of_code::{include_data, include_example};
|
||||
use advent_of_code_macros::{include_data, include_example};
|
||||
|
||||
include_example!(DATA 2023 02);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use advent_of_code::strings::{convert_to_array, parsenumber, splitspace};
|
||||
use advent_of_code::strings::{parsenumber, splitspace};
|
||||
#[allow(unused_imports)]
|
||||
use advent_of_code::{include_data, include_example};
|
||||
use advent_of_code_macros::{include_data, include_example};
|
||||
|
||||
include_data!(DATA 2024 01);
|
||||
|
||||
|
@ -37,7 +37,7 @@ fn similarity(leftlist: &Vec<u32>, rightlist: &Vec<u32>) -> u32 {
|
|||
fn main() {
|
||||
let mut leftlist = Vec::<u32>::with_capacity(1000);
|
||||
let mut rightlist = Vec::<u32>::with_capacity(1000);
|
||||
for (left, right) in convert_to_array::<_, _, '\n'>(DATA, splitspace) {
|
||||
for (left, right) in DATA.split("\n").map(splitspace) {
|
||||
leftlist.push(parsenumber(left));
|
||||
rightlist.push(parsenumber(right));
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use advent_of_code::strings::{convert_to_array, parsenumber};
|
||||
use advent_of_code::strings::parsenumber;
|
||||
#[allow(unused_imports)]
|
||||
use advent_of_code::{include_data, include_example};
|
||||
use advent_of_code_macros::{include_data, include_example};
|
||||
|
||||
include_data!(DATA 2024 02);
|
||||
|
||||
|
@ -101,7 +101,7 @@ fn safe(record: Vec<u32>) -> bool {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let numbers = convert_to_array::<_,_,'\n'>(DATA, get_numbers);
|
||||
let numbers = DATA.split('\n').map(get_numbers);
|
||||
let mut safe_reports = 0;
|
||||
let mut safe_with_dampener = 0;
|
||||
for report in numbers {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use advent_of_code::strings::parsenumber;
|
||||
#[allow(unused_imports)]
|
||||
use advent_of_code::{include_data, include_example};
|
||||
use advent_of_code_macros::{include_data, include_example};
|
||||
use regex::{Captures, Regex};
|
||||
|
||||
include_data!(DATA 2024 03);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use std::ops::RangeInclusive;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use advent_of_code::{include_data, include_example};
|
||||
use advent_of_code_macros::{include_data, include_example};
|
||||
|
||||
include_data!(DATA 2024 04);
|
||||
|
||||
|
|
|
@ -1,173 +0,0 @@
|
|||
#[allow(unused_imports)]
|
||||
use advent_of_code::{
|
||||
include_data, include_example,
|
||||
strings::{convert_to_array, line_to_char},
|
||||
KartesianDirection,
|
||||
};
|
||||
use advent_of_code::{Kartesian, Table};
|
||||
use log::debug;
|
||||
use num::Integer;
|
||||
|
||||
include_data!(DATA 2024 06);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct DirectionalKartesian<T: Integer> {
|
||||
x: T,
|
||||
y: T,
|
||||
dir: KartesianDirection,
|
||||
}
|
||||
impl<T: Integer> From<(Kartesian<T>, KartesianDirection)> for DirectionalKartesian<T> {
|
||||
fn from(value: (Kartesian<T>, KartesianDirection)) -> Self {
|
||||
DirectionalKartesian {
|
||||
x: value.0.x,
|
||||
y: value.0.y,
|
||||
dir: value.1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Integer + Copy> Into<(Kartesian<T>, KartesianDirection)> for &DirectionalKartesian<T> {
|
||||
fn into(self) -> (Kartesian<T>, KartesianDirection) {
|
||||
(
|
||||
Kartesian {
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
},
|
||||
self.dir,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Integer> DirectionalKartesian<T> {
|
||||
fn kartesian(self) -> Kartesian<T> {
|
||||
Kartesian::new(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
fn find_guard(map: Table) -> Kartesian<i32> {
|
||||
let mut position = Kartesian::default();
|
||||
for line in map {
|
||||
for char in line {
|
||||
if char == '^' {
|
||||
return position;
|
||||
}
|
||||
position.y += 1;
|
||||
}
|
||||
position.y = 0;
|
||||
position.x += 1;
|
||||
}
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn get_path(map: Table) -> Vec<DirectionalKartesian<i32>> {
|
||||
let mut position = (find_guard(map.clone()), KartesianDirection::Top);
|
||||
let maximum = Kartesian::new(map.len() as i32, map[0].len() as i32);
|
||||
debug!(
|
||||
"Guard is on coordinate {}:{}",
|
||||
position.0.x + 1,
|
||||
position.0.y + 1
|
||||
);
|
||||
let mut passed = Vec::new();
|
||||
passed.push(position.into());
|
||||
loop {
|
||||
position.0 = match position.0.checked_add_max(position.1.vector(), maximum) {
|
||||
None => {
|
||||
debug!("Guard left the space after {} steps", passed.len());
|
||||
return passed;
|
||||
}
|
||||
Some(pos) => pos,
|
||||
};
|
||||
if map[position.0.x as usize][position.0.y as usize] != '#' {
|
||||
passed.push(position.into());
|
||||
continue;
|
||||
}
|
||||
position.0 -= position.1.vector();
|
||||
debug!(
|
||||
"Guard turned right on {}:{}",
|
||||
position.0.x + 1,
|
||||
position.0.y + 1
|
||||
);
|
||||
position.1 = position.1.clockwise(false);
|
||||
}
|
||||
}
|
||||
|
||||
fn solver1(input: &str) -> usize {
|
||||
let map = convert_to_array(input, line_to_char);
|
||||
let mut path = get_path(map);
|
||||
path.sort();
|
||||
path.dedup_by_key(|p| (p.x, p.y));
|
||||
path.len()
|
||||
}
|
||||
|
||||
fn is_looping(
|
||||
path: Vec<DirectionalKartesian<i32>>,
|
||||
start_point: DirectionalKartesian<i32>,
|
||||
) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[allow(unused_variables, unused_mut)]
|
||||
fn solver2(input: &str) -> usize {
|
||||
let map = convert_to_array(input, line_to_char);
|
||||
let maximum = Kartesian::new(map.len() as i32, map[0].len() as i32);
|
||||
let mut path = get_path(map.clone());
|
||||
let mut p = path.iter();
|
||||
let mut looppoints = Vec::new();
|
||||
let startpoint = p.next().unwrap().kartesian();
|
||||
|
||||
let mut currentpoint: (Kartesian<i32>, KartesianDirection);
|
||||
for point in p {
|
||||
if point.kartesian() == startpoint {
|
||||
continue;
|
||||
}
|
||||
currentpoint = point.into();
|
||||
currentpoint.1 = currentpoint.1.clockwise(false);
|
||||
loop {
|
||||
currentpoint.0 = match currentpoint
|
||||
.0
|
||||
.checked_add_max(currentpoint.1.vector(), maximum)
|
||||
{
|
||||
None => break,
|
||||
Some(p) => p,
|
||||
};
|
||||
if path.contains(¤tpoint.into()) {
|
||||
looppoints.push(point.kartesian());
|
||||
break;
|
||||
}
|
||||
if map[currentpoint.0.x as usize][currentpoint.0.y as usize] == '#' {
|
||||
currentpoint.0 -= currentpoint.1.vector();
|
||||
currentpoint.1 = currentpoint.1.clockwise(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
looppoints.dedup();
|
||||
looppoints.len()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!(
|
||||
"Guard left the space after walking through {} distinct positions",
|
||||
solver1(DATA)
|
||||
);
|
||||
println!(
|
||||
"There are {} positions that are good for loops",
|
||||
solver2(DATA)
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
include_example!(EXAMPLE 2024 06);
|
||||
|
||||
#[test]
|
||||
fn test_solution_1() {
|
||||
assert_eq!(solver1(EXAMPLE), 41);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solution_2() {
|
||||
assert_eq!(solver2(EXAMPLE), 6);
|
||||
}
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
#![cfg_attr(debug_assertions, allow(unused_imports))]
|
||||
use std::ops::{Add, AddAssign, BitXor, Mul};
|
||||
|
||||
use advent_of_code::{
|
||||
numberlength,
|
||||
strings::{convert_to_array, parsenumber},
|
||||
};
|
||||
use advent_of_code_macros::{include_data, include_example};
|
||||
use log::*;
|
||||
use num::{pow::Pow, Integer};
|
||||
|
||||
include_data!(DATA 2024 07);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum Operation {
|
||||
Add,
|
||||
Multiply,
|
||||
Concat,
|
||||
}
|
||||
|
||||
impl Operation {
|
||||
fn op<
|
||||
T: Integer
|
||||
+ Add
|
||||
+ Mul
|
||||
+ Pow<u32, Output = T>
|
||||
+ std::ops::DivAssign
|
||||
+ AddAssign
|
||||
+ From<u32>
|
||||
+ Copy,
|
||||
>(
|
||||
self,
|
||||
a: T,
|
||||
b: T,
|
||||
) -> T {
|
||||
match self {
|
||||
Operation::Add => a + b,
|
||||
Operation::Multiply => a * b,
|
||||
Operation::Concat => {
|
||||
let ta = a * T::from(10).pow(numberlength(b));
|
||||
ta + b
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_data(line: &str) -> (u64, Vec<u64>) {
|
||||
let (result, numbers) = line.split_once(':').unwrap();
|
||||
|
||||
(
|
||||
parsenumber(result.trim()),
|
||||
Vec::from(convert_to_array::<_, _, ' '>(numbers, parsenumber)),
|
||||
)
|
||||
}
|
||||
|
||||
fn test_equation(result: u64, numbers: Vec<u64>, ops: Vec<Operation>) -> bool {
|
||||
let mut numberiter = numbers.iter();
|
||||
let mut opiter = ops.iter();
|
||||
let mut calcresult = numberiter.next().unwrap().clone();
|
||||
let mut next_number;
|
||||
debug_assert!(numbers.len() - 1 == ops.len());
|
||||
loop {
|
||||
next_number = numberiter.next().cloned();
|
||||
if next_number.is_none() {
|
||||
return calcresult == result;
|
||||
}
|
||||
calcresult = opiter.next().unwrap().op(calcresult, next_number.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_ops(len: usize, conf: usize) -> Vec<Operation> {
|
||||
let mut shift = 0;
|
||||
let mut ops = Vec::with_capacity(len);
|
||||
loop {
|
||||
match (conf & (0b1 << shift)) >> shift {
|
||||
0 => ops.push(Operation::Add),
|
||||
1 => ops.push(Operation::Multiply),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
shift += 1;
|
||||
if ops.len() == len {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ops
|
||||
}
|
||||
|
||||
fn get_ops_with_concat(len: u32) -> Vec<Vec<Operation>> {
|
||||
let mut ops = Vec::with_capacity(3u64.saturating_pow(len) as usize);
|
||||
for i in [Operation::Add, Operation::Concat, Operation::Multiply] {
|
||||
if len > 1 {
|
||||
for mut oplist in get_ops_with_concat(len - 1) {
|
||||
oplist.insert(0, i);
|
||||
ops.push(oplist);
|
||||
}
|
||||
} else {
|
||||
ops.push(vec![i]);
|
||||
}
|
||||
}
|
||||
ops
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pow2(i: usize) -> usize {
|
||||
2_u64.pow(i as u32) as usize - 1
|
||||
}
|
||||
|
||||
fn solution1(data: Vec<(u64, Vec<u64>)>) -> u64 {
|
||||
let mut output = 0;
|
||||
for line in data {
|
||||
for i in 0..=pow2(line.1.len()) {
|
||||
if test_equation(line.0, line.1.clone(), get_ops(line.1.len() - 1, i)) {
|
||||
output += line.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
fn solution2(data: Vec<(u64, Vec<u64>)>) -> u128 {
|
||||
let mut output = 0;
|
||||
for line in data {
|
||||
for ops in get_ops_with_concat((line.1.len() - 1) as u32) {
|
||||
if test_equation(line.0, line.1.clone(), ops) {
|
||||
output += line.0 as u128;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let data = convert_to_array::<_, _, '\n'>(DATA, get_data);
|
||||
println!("Found Calibration Total: {}", solution1(data.clone()));
|
||||
println!("Calibration total with Concat: {}", solution2(data.clone()));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_test_equation() {
|
||||
for c in [
|
||||
(
|
||||
190,
|
||||
Vec::from([10, 19]),
|
||||
Vec::from([Operation::Multiply]),
|
||||
true,
|
||||
),
|
||||
(
|
||||
3267,
|
||||
Vec::from([81, 40, 27]),
|
||||
Vec::from([Operation::Add, Operation::Multiply]),
|
||||
true,
|
||||
),
|
||||
(
|
||||
3267,
|
||||
Vec::from([81, 40, 27]),
|
||||
Vec::from([Operation::Multiply, Operation::Add]),
|
||||
true,
|
||||
),
|
||||
(
|
||||
292,
|
||||
Vec::from([11, 6, 16, 20]),
|
||||
Vec::from([Operation::Add, Operation::Multiply, Operation::Add]),
|
||||
true,
|
||||
),
|
||||
(
|
||||
292,
|
||||
Vec::from([11, 6, 16, 20]),
|
||||
Vec::from([Operation::Add, Operation::Multiply, Operation::Multiply]),
|
||||
false,
|
||||
),
|
||||
] {
|
||||
assert_eq!(test_equation(c.0, c.1.into(), c.2.into()), c.3)
|
||||
}
|
||||
}
|
||||
}
|
280
src/lib.rs
280
src/lib.rs
|
@ -1,281 +1 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,56 +1,51 @@
|
|||
use num::{pow::Pow, Integer};
|
||||
use std::ops::AddAssign;
|
||||
const MAXMUL: u32 = 100000;
|
||||
|
||||
pub fn splitspace(input: &str) -> (&str, &str) {
|
||||
let mut output = input.split_ascii_whitespace();
|
||||
(output.next().unwrap().trim(), output.next().unwrap().trim())
|
||||
(output.next().unwrap(), output.next().unwrap())
|
||||
}
|
||||
|
||||
pub fn parsenumber<T: Integer + From<u32> + Pow<u32, Output = T> + AddAssign + Copy>(
|
||||
input: &str,
|
||||
) -> T {
|
||||
const MAX_POWER: u32 = 32;
|
||||
let base = T::from(10);
|
||||
let mut output: T = T::from(0);
|
||||
let mut mul: u32 = 0;
|
||||
pub fn parsenumber(input: &str) -> u32 {
|
||||
let mut output = 0;
|
||||
let mut mul = 1;
|
||||
for c in input.chars().rev() {
|
||||
let i: T = match c {
|
||||
'1' => T::from(1),
|
||||
'2' => T::from(2),
|
||||
'3' => T::from(3),
|
||||
'4' => T::from(4),
|
||||
'5' => T::from(5),
|
||||
'6' => T::from(6),
|
||||
'7' => T::from(7),
|
||||
'8' => T::from(8),
|
||||
'9' => T::from(9),
|
||||
'0' => T::from(0),
|
||||
_ => unreachable!(),
|
||||
let i: u32 = match c {
|
||||
'1' => 1,
|
||||
'2' => 2,
|
||||
'3' => 3,
|
||||
'4' => 4,
|
||||
'5' => 5,
|
||||
'6' => 6,
|
||||
'7' => 7,
|
||||
'8' => 8,
|
||||
'9' => 9,
|
||||
'0' => 0,
|
||||
_ => 0,
|
||||
};
|
||||
if mul > MAX_POWER {
|
||||
if mul > MAXMUL {
|
||||
return output;
|
||||
}
|
||||
output += i * base.pow(mul);
|
||||
mul += 1;
|
||||
output += i * mul;
|
||||
mul *= 10;
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
pub fn get_numbers<T: Integer + From<u32>>(input: &str) -> Vec<T> {
|
||||
pub fn get_numbers(input: &str) -> Vec<u32> {
|
||||
let mut numbers = Vec::new();
|
||||
for char in input.chars() {
|
||||
match char {
|
||||
'1' => numbers.push(T::from(1)),
|
||||
'2' => numbers.push(T::from(2)),
|
||||
'3' => numbers.push(T::from(3)),
|
||||
'4' => numbers.push(T::from(4)),
|
||||
'5' => numbers.push(T::from(5)),
|
||||
'6' => numbers.push(T::from(6)),
|
||||
'7' => numbers.push(T::from(7)),
|
||||
'8' => numbers.push(T::from(8)),
|
||||
'9' => numbers.push(T::from(9)),
|
||||
'0' => numbers.push(T::from(0)),
|
||||
_ => unimplemented!(),
|
||||
'1' => numbers.push(1),
|
||||
'2' => numbers.push(2),
|
||||
'3' => numbers.push(3),
|
||||
'4' => numbers.push(4),
|
||||
'5' => numbers.push(5),
|
||||
'6' => numbers.push(6),
|
||||
'7' => numbers.push(7),
|
||||
'8' => numbers.push(8),
|
||||
'9' => numbers.push(9),
|
||||
'0' => numbers.push(0),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
numbers
|
||||
|
@ -161,17 +156,3 @@ pub fn get_string_numbers(input: &str) -> Vec<u32> {
|
|||
}
|
||||
output
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn line_to_char(line: &str) -> Vec<char> {
|
||||
Vec::from_iter(line.chars())
|
||||
}
|
||||
|
||||
pub fn convert_to_array<T, F: FnMut(&str) -> T, const S: char>(input: &str, func: F) -> Vec<T> {
|
||||
input
|
||||
.trim()
|
||||
.split(S)
|
||||
.map(str::trim_ascii)
|
||||
.map(func)
|
||||
.collect()
|
||||
}
|
||||
|
|
Laden …
Tabelle hinzufügen
In neuem Issue referenzieren