applied clippy
This commit is contained in:
parent
33eb92e9d1
commit
4e08117ed0
16 changed files with 205 additions and 504 deletions
|
|
@ -7,4 +7,5 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
itertools = "0.10"
|
itertools = "0.10"
|
||||||
|
num-traits = "0.2.15"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
use super::{number::Number, pos::Pos};
|
use num_traits::{Num, NumAssignOps};
|
||||||
|
|
||||||
|
use super::pos::Pos;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
pub struct Area<T>
|
pub struct Area<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num,
|
||||||
{
|
{
|
||||||
lower_left: Pos<T>,
|
lower_left: Pos<T>,
|
||||||
upper_right: Pos<T>,
|
upper_right: Pos<T>,
|
||||||
|
|
@ -14,7 +16,7 @@ where
|
||||||
|
|
||||||
impl<T> Area<T>
|
impl<T> Area<T>
|
||||||
where
|
where
|
||||||
T: Number + Ord,
|
T: Num + Ord + Copy,
|
||||||
{
|
{
|
||||||
pub fn new(p1: Pos<T>, p2: Pos<T>) -> Area<T> {
|
pub fn new(p1: Pos<T>, p2: Pos<T>) -> Area<T> {
|
||||||
Area {
|
Area {
|
||||||
|
|
@ -22,7 +24,12 @@ where
|
||||||
upper_right: p1.max_components(&p2),
|
upper_right: p1.max_components(&p2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Area<T>
|
||||||
|
where
|
||||||
|
T: Num + Ord + Copy,
|
||||||
|
{
|
||||||
pub fn extend(&self, pos: Pos<T>) -> Area<T> {
|
pub fn extend(&self, pos: Pos<T>) -> Area<T> {
|
||||||
if self.contains(pos) {
|
if self.contains(pos) {
|
||||||
return *self;
|
return *self;
|
||||||
|
|
@ -33,7 +40,6 @@ where
|
||||||
upper_right: self.upper_right.max_components(&pos),
|
upper_right: self.upper_right.max_components(&pos),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_lower_left(&self) -> Pos<T> {
|
pub fn get_lower_left(&self) -> Pos<T> {
|
||||||
self.lower_left
|
self.lower_left
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +58,7 @@ where
|
||||||
|
|
||||||
impl<'a, T> Area<T>
|
impl<'a, T> Area<T>
|
||||||
where
|
where
|
||||||
T: Number + Ord + 'a,
|
T: Num + Ord + 'a + Copy,
|
||||||
{
|
{
|
||||||
pub fn from_iterator<I>(mut iter: I) -> Option<Self>
|
pub fn from_iterator<I>(mut iter: I) -> Option<Self>
|
||||||
where
|
where
|
||||||
|
|
@ -60,7 +66,7 @@ where
|
||||||
{
|
{
|
||||||
let first = *iter.next()?;
|
let first = *iter.next()?;
|
||||||
let (upper, lower) = iter.fold((first, first), |(mx, mn), p| {
|
let (upper, lower) = iter.fold((first, first), |(mx, mn), p| {
|
||||||
(mx.max_components(&p), mn.min_components(&p))
|
(mx.max_components(p), mn.min_components(p))
|
||||||
});
|
});
|
||||||
|
|
||||||
Some(Area::new(lower, upper))
|
Some(Area::new(lower, upper))
|
||||||
|
|
@ -69,21 +75,21 @@ where
|
||||||
|
|
||||||
impl<T> Area<T>
|
impl<T> Area<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
pub fn width(&self) -> T {
|
pub fn width(&self) -> T {
|
||||||
self.upper_right.x() - self.lower_left.x() + T::ONE
|
self.upper_right.x() - self.lower_left.x() + T::one()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn height(&self) -> T {
|
pub fn height(&self) -> T {
|
||||||
self.upper_right.y() - self.lower_left.y() + T::ONE
|
self.upper_right.y() - self.lower_left.y() + T::one()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Area<T>
|
impl<T> Area<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn area(&self) -> T {
|
pub fn area(&self) -> T {
|
||||||
|
|
@ -93,7 +99,7 @@ where
|
||||||
|
|
||||||
impl<T> Display for Area<T>
|
impl<T> Display for Area<T>
|
||||||
where
|
where
|
||||||
T: Number + Display,
|
T: Num + Display,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "[{}-{}]", self.lower_left, self.upper_right)
|
write!(f, "[{}-{}]", self.lower_left, self.upper_right)
|
||||||
|
|
@ -102,7 +108,7 @@ where
|
||||||
|
|
||||||
impl<T> Area<T>
|
impl<T> Area<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
pub fn cells(&self, ascending: bool) -> CellIterator<'_, T> {
|
pub fn cells(&self, ascending: bool) -> CellIterator<'_, T> {
|
||||||
CellIterator::new(self, ascending)
|
CellIterator::new(self, ascending)
|
||||||
|
|
@ -116,7 +122,7 @@ where
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RowIterator<'a, T>
|
pub struct RowIterator<'a, T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
area: &'a Area<T>,
|
area: &'a Area<T>,
|
||||||
row: T,
|
row: T,
|
||||||
|
|
@ -125,7 +131,7 @@ where
|
||||||
|
|
||||||
impl<'a, T> RowIterator<'a, T>
|
impl<'a, T> RowIterator<'a, T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
fn new(area: &'a Area<T>, ascending: bool) -> RowIterator<'a, T> {
|
fn new(area: &'a Area<T>, ascending: bool) -> RowIterator<'a, T> {
|
||||||
RowIterator {
|
RowIterator {
|
||||||
|
|
@ -142,7 +148,7 @@ where
|
||||||
|
|
||||||
impl<'a, T> Iterator for RowIterator<'a, T>
|
impl<'a, T> Iterator for RowIterator<'a, T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Ord + NumAssignOps + Copy,
|
||||||
{
|
{
|
||||||
type Item = Row<'a, T>;
|
type Item = Row<'a, T>;
|
||||||
|
|
||||||
|
|
@ -155,9 +161,9 @@ where
|
||||||
row: self.row,
|
row: self.row,
|
||||||
};
|
};
|
||||||
if self.ascending {
|
if self.ascending {
|
||||||
self.row += T::ONE;
|
self.row += T::one();
|
||||||
} else {
|
} else {
|
||||||
self.row -= T::ONE;
|
self.row -= T::one();
|
||||||
}
|
}
|
||||||
Some(row)
|
Some(row)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -169,7 +175,7 @@ where
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Row<'a, T>
|
pub struct Row<'a, T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num,
|
||||||
{
|
{
|
||||||
area: &'a Area<T>,
|
area: &'a Area<T>,
|
||||||
row: T,
|
row: T,
|
||||||
|
|
@ -177,7 +183,7 @@ where
|
||||||
|
|
||||||
impl<'a, T> Row<'a, T>
|
impl<'a, T> Row<'a, T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
pub fn cols(&self, ascending: bool) -> ColIterator<'_, T> {
|
pub fn cols(&self, ascending: bool) -> ColIterator<'_, T> {
|
||||||
ColIterator {
|
ColIterator {
|
||||||
|
|
@ -196,7 +202,7 @@ where
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ColIterator<'a, T>
|
pub struct ColIterator<'a, T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num,
|
||||||
{
|
{
|
||||||
area: &'a Area<T>,
|
area: &'a Area<T>,
|
||||||
row: T,
|
row: T,
|
||||||
|
|
@ -206,7 +212,7 @@ where
|
||||||
|
|
||||||
impl<'a, T> Iterator for ColIterator<'a, T>
|
impl<'a, T> Iterator for ColIterator<'a, T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Ord + NumAssignOps + Copy,
|
||||||
{
|
{
|
||||||
type Item = Pos<T>;
|
type Item = Pos<T>;
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
|
@ -215,10 +221,10 @@ where
|
||||||
{
|
{
|
||||||
let pos = Pos::new(self.col, self.row);
|
let pos = Pos::new(self.col, self.row);
|
||||||
if self.ascending {
|
if self.ascending {
|
||||||
self.col += T::ONE
|
self.col += T::one();
|
||||||
} else {
|
} else {
|
||||||
self.col -= T::ONE
|
self.col -= T::one();
|
||||||
};
|
}
|
||||||
Some(pos)
|
Some(pos)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -229,7 +235,7 @@ where
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CellIterator<'a, T>
|
pub struct CellIterator<'a, T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num,
|
||||||
{
|
{
|
||||||
area: &'a Area<T>,
|
area: &'a Area<T>,
|
||||||
row: T,
|
row: T,
|
||||||
|
|
@ -239,7 +245,7 @@ where
|
||||||
|
|
||||||
impl<'a, T> CellIterator<'a, T>
|
impl<'a, T> CellIterator<'a, T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
pub fn new(area: &'a Area<T>, ascending: bool) -> CellIterator<'a, T> {
|
pub fn new(area: &'a Area<T>, ascending: bool) -> CellIterator<'a, T> {
|
||||||
let (col, row) = if ascending {
|
let (col, row) = if ascending {
|
||||||
|
|
@ -258,7 +264,7 @@ where
|
||||||
|
|
||||||
impl<'a, T> Iterator for CellIterator<'a, T>
|
impl<'a, T> Iterator for CellIterator<'a, T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Ord + NumAssignOps + Copy,
|
||||||
{
|
{
|
||||||
type Item = Pos<T>;
|
type Item = Pos<T>;
|
||||||
|
|
||||||
|
|
@ -268,15 +274,15 @@ where
|
||||||
{
|
{
|
||||||
let pos = Pos::new(self.col, self.row);
|
let pos = Pos::new(self.col, self.row);
|
||||||
if self.ascending {
|
if self.ascending {
|
||||||
self.col += T::ONE;
|
self.col += T::one();
|
||||||
if self.col > self.area.upper_right.x() {
|
if self.col > self.area.upper_right.x() {
|
||||||
self.row += T::ONE;
|
self.row += T::one();
|
||||||
self.col = self.area.lower_left.x();
|
self.col = self.area.lower_left.x();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.col -= T::ONE;
|
self.col -= T::one();
|
||||||
if self.col < self.area.lower_left.x() {
|
if self.col < self.area.lower_left.x() {
|
||||||
self.row -= T::ONE;
|
self.row -= T::one();
|
||||||
self.col = self.area.upper_right.x();
|
self.col = self.area.upper_right.x();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use itertools::Itertools;
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
|
|
||||||
fn read_data(day_num: usize, file: &str) -> io::Result<String> {
|
fn read_data(day_num: usize, file: &str) -> io::Result<String> {
|
||||||
fs::read_to_string(format!("data/day{:02}/{}", day_num, file))
|
fs::read_to_string(format!("data/day{day_num:02}/{file}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_lines(day_num: usize, file: &str) -> io::Result<Vec<String>> {
|
pub fn read_lines(day_num: usize, file: &str) -> io::Result<Vec<String>> {
|
||||||
|
|
@ -15,7 +15,7 @@ pub fn read_lines(day_num: usize, file: &str) -> io::Result<Vec<String>> {
|
||||||
| itertools::Position::Middle(line)
|
| itertools::Position::Middle(line)
|
||||||
| itertools::Position::Only(line) => Some(line.to_owned()),
|
| itertools::Position::Only(line) => Some(line.to_owned()),
|
||||||
itertools::Position::Last(line) => {
|
itertools::Position::Last(line) => {
|
||||||
if line.len() == 0 {
|
if line.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(line.to_owned())
|
Some(line.to_owned())
|
||||||
|
|
|
||||||
|
|
@ -74,21 +74,3 @@ pub fn zip7<A, B, C, D, E, F, G>(
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zip8<A, B, C, D, E, F, G, H>(
|
|
||||||
o1: Option<A>,
|
|
||||||
o2: Option<B>,
|
|
||||||
o3: Option<C>,
|
|
||||||
o4: Option<D>,
|
|
||||||
o5: Option<E>,
|
|
||||||
o6: Option<F>,
|
|
||||||
o7: Option<G>,
|
|
||||||
o8: Option<H>,
|
|
||||||
) -> Option<(A, B, C, D, E, F, G, H)> {
|
|
||||||
match (o1, o2, o3, o4, o5, o6, o7, o8) {
|
|
||||||
(Some(a), Some(b), Some(c), Some(d), Some(e), Some(f), Some(g), Some(h)) => {
|
|
||||||
Some((a, b, c, d, e, f, g, h))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use super::number::Number;
|
use num_traits::{Euclid, Num};
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum MathError {
|
pub enum MathError {
|
||||||
|
|
@ -17,35 +17,36 @@ pub enum MathError {
|
||||||
|
|
||||||
fn non_zero_gcd<T>(mut a: T, mut b: T) -> T
|
fn non_zero_gcd<T>(mut a: T, mut b: T) -> T
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Ord + Copy,
|
||||||
{
|
{
|
||||||
while b != T::ZERO {
|
while !b.is_zero() {
|
||||||
let t = a % b;
|
let t = a % b;
|
||||||
a = b;
|
a = b;
|
||||||
b = t;
|
b = t;
|
||||||
}
|
}
|
||||||
a.abs()
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gcd<T>(a: T, b: T) -> T
|
pub fn gcd<T>(a: T, b: T) -> T
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Ord + Copy,
|
||||||
{
|
{
|
||||||
if a == T::ZERO {
|
assert!(a >= T::zero());
|
||||||
b.abs()
|
assert!(b >= T::zero());
|
||||||
} else if b == T::ZERO {
|
if a.is_zero() {
|
||||||
a.abs()
|
b
|
||||||
|
} else if b.is_zero() {
|
||||||
|
a
|
||||||
} else {
|
} else {
|
||||||
non_zero_gcd(a, b)
|
non_zero_gcd(a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lcm<T>(a: T, b: T) -> T
|
pub fn lcm<T>(a: T, b: T) -> T
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Ord + Copy,
|
||||||
{
|
{
|
||||||
if a == T::ZERO || b == T::ZERO {
|
if a.is_zero() || b.is_zero() {
|
||||||
T::ZERO
|
T::zero()
|
||||||
} else {
|
} else {
|
||||||
a * b / non_zero_gcd(a, b)
|
a * b / non_zero_gcd(a, b)
|
||||||
}
|
}
|
||||||
|
|
@ -53,64 +54,20 @@ where
|
||||||
|
|
||||||
pub fn modulus_inv<T>(num: T, modulo: T) -> Option<T>
|
pub fn modulus_inv<T>(num: T, modulo: T) -> Option<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Euclid + Copy,
|
||||||
{
|
{
|
||||||
let num = num.rem_euclid(modulo);
|
let num = num.rem_euclid(&modulo);
|
||||||
let mut s = (T::ZERO, T::ONE);
|
let mut s = (T::zero(), T::one());
|
||||||
let mut r = (modulo, num);
|
let mut r = (modulo, num);
|
||||||
while r.0 != T::ZERO {
|
while !r.0.is_zero() {
|
||||||
let q = r.1 / r.0;
|
let q = r.1 / r.0;
|
||||||
r = (r.1 - q * r.0, r.0);
|
r = (r.1 - q * r.0, r.0);
|
||||||
s = (s.1 - q * s.0, s.0);
|
s = (s.1 - q * s.0, s.0);
|
||||||
}
|
}
|
||||||
if r.1 != T::ONE {
|
if !r.1.is_one() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(s.1.rem_euclid(modulo))
|
Some(s.1.rem_euclid(&modulo))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modulus_mul<T>(a: T, b: T, modulo: T) -> Result<T, MathError>
|
|
||||||
where
|
|
||||||
T: Number,
|
|
||||||
{
|
|
||||||
let mul = if let Some(mul) = a.checked_mul(b) {
|
|
||||||
mul
|
|
||||||
} else if T::MAX >> T::ONE >= a {
|
|
||||||
let start = if b.is_odd() { a } else { T::ZERO };
|
|
||||||
start + modulus_mul((a << T::ONE).rem_euclid(modulo), b >> T::ONE, modulo)?
|
|
||||||
} else {
|
|
||||||
return Err(MathError::TooHigh);
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(mul.rem_euclid(modulo))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn modulus_exp<T>(base: T, exponent: T, modulo: T) -> Result<T, MathError>
|
|
||||||
where
|
|
||||||
T: Number,
|
|
||||||
{
|
|
||||||
if modulo < T::ONE {
|
|
||||||
return Err(MathError::NeedPositiveModulo);
|
|
||||||
}
|
|
||||||
if exponent < T::ZERO {
|
|
||||||
return Err(MathError::NeedNonNegativeExponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if modulo == T::ONE {
|
|
||||||
Ok(T::ZERO)
|
|
||||||
} else {
|
|
||||||
let mut result = T::ONE;
|
|
||||||
let mut base = base.rem_euclid(modulo);
|
|
||||||
let mut exponent = exponent;
|
|
||||||
while exponent > T::ZERO {
|
|
||||||
if exponent.is_odd() {
|
|
||||||
result = modulus_mul(result, base, modulo)?;
|
|
||||||
}
|
|
||||||
exponent = exponent >> T::ONE;
|
|
||||||
base = modulus_mul(base, base, modulo)?;
|
|
||||||
}
|
|
||||||
Ok(result)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,29 +88,6 @@ mod tests {
|
||||||
assert_eq!(20, lcm(5, 4));
|
assert_eq!(20, lcm(5, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_modulo_mul() -> Result<(), MathError> {
|
|
||||||
let a = 1_234_567_890_123_456i64;
|
|
||||||
let b = 98_765;
|
|
||||||
let result = modulus_mul(a, b, 3_333_333_333_333_333)?;
|
|
||||||
|
|
||||||
assert_eq!(result, 2_097_668_043_144_033);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_modulo_exp() -> Result<(), MathError> {
|
|
||||||
let base = 4;
|
|
||||||
let exponent = 13;
|
|
||||||
let modulo = 497;
|
|
||||||
let result = modulus_exp(base, exponent, modulo)?;
|
|
||||||
|
|
||||||
assert_eq!(result, 445);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_inverse_modulo() {
|
fn test_inverse_modulo() {
|
||||||
let num = 3;
|
let num = 3;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,5 @@ pub mod direction;
|
||||||
pub mod file;
|
pub mod file;
|
||||||
pub mod helper;
|
pub mod helper;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
pub mod number;
|
|
||||||
pub mod permutations;
|
|
||||||
pub mod pos;
|
pub mod pos;
|
||||||
pub mod turn;
|
pub mod turn;
|
||||||
|
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
use std::ops::{Add, AddAssign, BitAnd, Div, Mul, Rem, Shl, Shr, Sub, SubAssign};
|
|
||||||
|
|
||||||
pub trait Number:
|
|
||||||
Copy
|
|
||||||
+ Add<Output = Self>
|
|
||||||
+ Sub<Output = Self>
|
|
||||||
+ Mul<Output = Self>
|
|
||||||
+ Div<Output = Self>
|
|
||||||
+ Rem<Output = Self>
|
|
||||||
+ Shr<Output = Self>
|
|
||||||
+ Shl<Output = Self>
|
|
||||||
+ AddAssign
|
|
||||||
+ SubAssign
|
|
||||||
+ BitAnd<Output = Self>
|
|
||||||
+ PartialEq
|
|
||||||
+ PartialOrd
|
|
||||||
+ Ord
|
|
||||||
{
|
|
||||||
const ZERO: Self;
|
|
||||||
const ONE: Self;
|
|
||||||
const MAX: Self;
|
|
||||||
|
|
||||||
fn abs(self) -> Self;
|
|
||||||
fn checked_mul(self, rhs: Self) -> Option<Self>;
|
|
||||||
fn rem_euclid(self, rhs: Self) -> Self;
|
|
||||||
|
|
||||||
fn is_odd(&self) -> bool {
|
|
||||||
*self & Self::ONE == Self::ONE
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_even(&self) -> bool {
|
|
||||||
!self.is_odd()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_f64(self) -> f64;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Number for i32 {
|
|
||||||
const ZERO: i32 = 0i32;
|
|
||||||
const ONE: i32 = 1i32;
|
|
||||||
const MAX: i32 = i32::MAX;
|
|
||||||
|
|
||||||
fn abs(self) -> Self {
|
|
||||||
(self as i32).abs()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rem_euclid(self, rhs: Self) -> Self {
|
|
||||||
(self as i32).rem_euclid(rhs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn checked_mul(self, rhs: Self) -> Option<Self> {
|
|
||||||
(self as i32).checked_mul(rhs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_f64(self) -> f64 {
|
|
||||||
self as f64
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Number for i64 {
|
|
||||||
const ZERO: i64 = 0i64;
|
|
||||||
const ONE: i64 = 1i64;
|
|
||||||
const MAX: i64 = i64::MAX;
|
|
||||||
|
|
||||||
fn abs(self) -> Self {
|
|
||||||
(self as i64).abs()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rem_euclid(self, rhs: Self) -> Self {
|
|
||||||
(self as i64).rem_euclid(rhs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn checked_mul(self, rhs: Self) -> Option<Self> {
|
|
||||||
(self as i64).checked_mul(rhs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_f64(self) -> f64 {
|
|
||||||
self as f64
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Number for i128 {
|
|
||||||
const ZERO: i128 = 0i128;
|
|
||||||
const ONE: i128 = 1i128;
|
|
||||||
const MAX: i128 = i128::MAX;
|
|
||||||
|
|
||||||
fn abs(self) -> Self {
|
|
||||||
(self as i128).abs()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rem_euclid(self, rhs: Self) -> Self {
|
|
||||||
(self as i128).rem_euclid(rhs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn checked_mul(self, rhs: Self) -> Option<Self> {
|
|
||||||
(self as i128).checked_mul(rhs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_f64(self) -> f64 {
|
|
||||||
self as f64
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,152 +0,0 @@
|
||||||
use std::{cell::RefCell, rc::Rc};
|
|
||||||
|
|
||||||
pub trait PermutateExt<T>: IntoIterator<Item = T> {
|
|
||||||
fn permutate(&self) -> Permutations<'_, T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> PermutateExt<T> for Vec<T> {
|
|
||||||
fn permutate(&self) -> Permutations<'_, T> {
|
|
||||||
let list = self.into_iter().collect::<Vec<_>>();
|
|
||||||
Permutations {
|
|
||||||
list: Rc::new(RefCell::new(list)),
|
|
||||||
|
|
||||||
start: 0,
|
|
||||||
current: 0,
|
|
||||||
len: self.len(),
|
|
||||||
maybe_tail: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Permutations<'a, T> {
|
|
||||||
list: Rc<RefCell<Vec<&'a T>>>,
|
|
||||||
start: usize,
|
|
||||||
current: usize,
|
|
||||||
len: usize,
|
|
||||||
maybe_tail: Option<Box<Permutations<'a, T>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T> Iterator for Permutations<'a, T> {
|
|
||||||
type Item = Vec<&'a T>;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Vec<&'a T>> {
|
|
||||||
if self.current >= self.len {
|
|
||||||
None
|
|
||||||
} else if self.start + 1 == self.len {
|
|
||||||
self.current += 1;
|
|
||||||
Some(self.list.borrow().clone())
|
|
||||||
} else {
|
|
||||||
if let Some(mut tail) = self.maybe_tail.take() {
|
|
||||||
if let Some(result) = tail.next() {
|
|
||||||
self.maybe_tail = Some(tail);
|
|
||||||
return Some(result);
|
|
||||||
} else {
|
|
||||||
let mut borrow = (*self.list).borrow_mut();
|
|
||||||
// Swapping prev first item back to its original osition
|
|
||||||
for p in self.start..self.current {
|
|
||||||
borrow.swap(p, p + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.current += 1;
|
|
||||||
if self.current >= self.len {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getting next first item for next iteration
|
|
||||||
for p in (self.start..self.current).rev() {
|
|
||||||
borrow.swap(p, p + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut rest = Box::new(Permutations {
|
|
||||||
len: self.len,
|
|
||||||
list: self.list.clone(),
|
|
||||||
current: self.start + 1,
|
|
||||||
start: self.start + 1,
|
|
||||||
maybe_tail: None,
|
|
||||||
});
|
|
||||||
let result = rest.next();
|
|
||||||
self.maybe_tail = Some(rest);
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_zero() {
|
|
||||||
let input: Vec<i32> = vec![];
|
|
||||||
let result = input.permutate().collect::<Vec<_>>();
|
|
||||||
let expected: Vec<Vec<&i32>> = vec![];
|
|
||||||
assert_eq!(result, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_one() {
|
|
||||||
let input = vec![1];
|
|
||||||
let result = input.permutate().collect::<Vec<_>>();
|
|
||||||
let expected = vec![[&1]];
|
|
||||||
assert_eq!(result, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_two() {
|
|
||||||
let input = vec![1, 2];
|
|
||||||
let result = input.permutate().collect::<Vec<_>>();
|
|
||||||
let expected = vec![[&1, &2], [&2, &1]];
|
|
||||||
assert_eq!(result, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_three() {
|
|
||||||
let input = vec![1, 2, 3];
|
|
||||||
let result = input.permutate().collect::<Vec<_>>();
|
|
||||||
let expected = vec![
|
|
||||||
[&1, &2, &3],
|
|
||||||
[&1, &3, &2],
|
|
||||||
[&2, &1, &3],
|
|
||||||
[&2, &3, &1],
|
|
||||||
[&3, &1, &2],
|
|
||||||
[&3, &2, &1],
|
|
||||||
];
|
|
||||||
assert_eq!(result, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_four() {
|
|
||||||
let input = vec![1, 2, 3, 4];
|
|
||||||
let result = input.permutate().collect::<Vec<_>>();
|
|
||||||
let expected = vec![
|
|
||||||
[&1, &2, &3, &4],
|
|
||||||
[&1, &2, &4, &3],
|
|
||||||
[&1, &3, &2, &4],
|
|
||||||
[&1, &3, &4, &2],
|
|
||||||
[&1, &4, &2, &3],
|
|
||||||
[&1, &4, &3, &2],
|
|
||||||
[&2, &1, &3, &4],
|
|
||||||
[&2, &1, &4, &3],
|
|
||||||
[&2, &3, &1, &4],
|
|
||||||
[&2, &3, &4, &1],
|
|
||||||
[&2, &4, &1, &3],
|
|
||||||
[&2, &4, &3, &1],
|
|
||||||
[&3, &1, &2, &4],
|
|
||||||
[&3, &1, &4, &2],
|
|
||||||
[&3, &2, &1, &4],
|
|
||||||
[&3, &2, &4, &1],
|
|
||||||
[&3, &4, &1, &2],
|
|
||||||
[&3, &4, &2, &1],
|
|
||||||
[&4, &1, &2, &3],
|
|
||||||
[&4, &1, &3, &2],
|
|
||||||
[&4, &2, &1, &3],
|
|
||||||
[&4, &2, &3, &1],
|
|
||||||
[&4, &3, &1, &2],
|
|
||||||
[&4, &3, &2, &1],
|
|
||||||
];
|
|
||||||
assert_eq!(result, expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +1,27 @@
|
||||||
use super::{direction::Direction, math::gcd, number::Number};
|
use super::direction::Direction;
|
||||||
|
use super::math::gcd;
|
||||||
|
use num_traits::{Num, NumCast, Signed};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{Add, Mul, Sub};
|
use std::ops::{Add, Mul, Sub};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||||
pub struct Pos<T>(T, T)
|
pub struct Pos<T>(T, T)
|
||||||
where
|
where
|
||||||
T: Number;
|
T: Num;
|
||||||
|
|
||||||
impl<T> Pos<T>
|
impl<T> Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num,
|
||||||
{
|
{
|
||||||
pub fn new(x: T, y: T) -> Pos<T> {
|
pub fn new(x: T, y: T) -> Pos<T> {
|
||||||
Pos(x, y)
|
Pos(x, y)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Pos<T>
|
||||||
|
where
|
||||||
|
T: Num + Copy,
|
||||||
|
{
|
||||||
pub fn x(&self) -> T {
|
pub fn x(&self) -> T {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +29,47 @@ where
|
||||||
pub fn y(&self) -> T {
|
pub fn y(&self) -> T {
|
||||||
self.1
|
self.1
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Pos<T>
|
||||||
|
where
|
||||||
|
T: Num + Ord + Copy,
|
||||||
|
{
|
||||||
|
pub fn normalize(&self) -> (Pos<T>, T) {
|
||||||
|
if self.0.is_zero() && self.1.is_zero() {
|
||||||
|
(*self, T::one())
|
||||||
|
} else {
|
||||||
|
let ggt = gcd(self.0, self.1);
|
||||||
|
(Pos::new(self.0 / ggt, self.1 / ggt), ggt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Pos<T>
|
||||||
|
where
|
||||||
|
T: Num + NumCast,
|
||||||
|
{
|
||||||
|
pub fn angle(&self) -> f64 {
|
||||||
|
if let (Some(x), Some(y)) = (self.0.to_f64(), self.1.to_f64()) {
|
||||||
|
y.atan2(x)
|
||||||
|
} else {
|
||||||
|
f64::NAN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn angle2(&self) -> f64 {
|
||||||
|
if let (Some(x), Some(y)) = (self.0.to_f64(), self.1.to_f64()) {
|
||||||
|
(-x.atan2(-y) + std::f64::consts::PI).rem_euclid(2.0 * std::f64::consts::PI)
|
||||||
|
} else {
|
||||||
|
f64::NAN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Pos<T>
|
||||||
|
where
|
||||||
|
T: Num + Ord + Copy,
|
||||||
|
{
|
||||||
pub fn max_components(&self, other: &Pos<T>) -> Self {
|
pub fn max_components(&self, other: &Pos<T>) -> Self {
|
||||||
Self(self.0.max(other.0), self.1.max(other.1))
|
Self(self.0.max(other.0), self.1.max(other.1))
|
||||||
}
|
}
|
||||||
|
|
@ -30,33 +77,20 @@ where
|
||||||
pub fn min_components(&self, other: &Pos<T>) -> Self {
|
pub fn min_components(&self, other: &Pos<T>) -> Self {
|
||||||
Self(self.0.min(other.0), self.1.min(other.1))
|
Self(self.0.min(other.0), self.1.min(other.1))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Pos<T>
|
||||||
|
where
|
||||||
|
T: Num + Signed,
|
||||||
|
{
|
||||||
pub fn abs(&self) -> T {
|
pub fn abs(&self) -> T {
|
||||||
self.0.abs() + self.1.abs()
|
self.0.abs() + self.1.abs()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn normalize(&self) -> (Pos<T>, T) {
|
|
||||||
if self.0 == T::ZERO && self.1 == T::ZERO {
|
|
||||||
(*self, T::ONE)
|
|
||||||
} else {
|
|
||||||
let ggt = gcd(self.0, self.1);
|
|
||||||
(Pos::new(self.0 / ggt, self.1 / ggt), ggt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn angle(&self) -> f64 {
|
|
||||||
self.1.as_f64().atan2(self.0.as_f64())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn angle2(&self) -> f64 {
|
|
||||||
(-self.0.as_f64().atan2(-self.1.as_f64()) + std::f64::consts::PI)
|
|
||||||
.rem_euclid(2.0 * std::f64::consts::PI)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> fmt::Display for Pos<T>
|
impl<T> fmt::Display for Pos<T>
|
||||||
where
|
where
|
||||||
T: Number + fmt::Display,
|
T: Num + fmt::Display,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "({}, {})", self.0, self.1)
|
write!(f, "({}, {})", self.0, self.1)
|
||||||
|
|
@ -65,7 +99,7 @@ where
|
||||||
|
|
||||||
impl<T> Add for Pos<T>
|
impl<T> Add for Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num,
|
||||||
{
|
{
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn add(self, rhs: Self) -> Self::Output {
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
|
@ -75,7 +109,7 @@ where
|
||||||
|
|
||||||
impl<T> Add for &Pos<T>
|
impl<T> Add for &Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
type Output = <Pos<T> as Add<Pos<T>>>::Output;
|
type Output = <Pos<T> as Add<Pos<T>>>::Output;
|
||||||
|
|
||||||
|
|
@ -86,7 +120,7 @@ where
|
||||||
|
|
||||||
impl<T> Add<&Pos<T>> for Pos<T>
|
impl<T> Add<&Pos<T>> for Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
type Output = <Pos<T> as Add<Pos<T>>>::Output;
|
type Output = <Pos<T> as Add<Pos<T>>>::Output;
|
||||||
fn add(self, rhs: &Self) -> Self::Output {
|
fn add(self, rhs: &Self) -> Self::Output {
|
||||||
|
|
@ -96,7 +130,7 @@ where
|
||||||
|
|
||||||
impl<T> Add<Pos<T>> for &Pos<T>
|
impl<T> Add<Pos<T>> for &Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
type Output = <Pos<T> as Add<Pos<T>>>::Output;
|
type Output = <Pos<T> as Add<Pos<T>>>::Output;
|
||||||
fn add(self, rhs: Pos<T>) -> Self::Output {
|
fn add(self, rhs: Pos<T>) -> Self::Output {
|
||||||
|
|
@ -106,7 +140,7 @@ where
|
||||||
|
|
||||||
impl<T> Add<(T, T)> for Pos<T>
|
impl<T> Add<(T, T)> for Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num,
|
||||||
{
|
{
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn add(self, rhs: (T, T)) -> Self::Output {
|
fn add(self, rhs: (T, T)) -> Self::Output {
|
||||||
|
|
@ -148,7 +182,7 @@ impl Add<Direction> for &Pos<i32> {
|
||||||
|
|
||||||
impl<T> Sub for Pos<T>
|
impl<T> Sub for Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num,
|
||||||
{
|
{
|
||||||
type Output = Pos<T>;
|
type Output = Pos<T>;
|
||||||
fn sub(self, rhs: Self) -> Self::Output {
|
fn sub(self, rhs: Self) -> Self::Output {
|
||||||
|
|
@ -158,7 +192,7 @@ where
|
||||||
|
|
||||||
impl<T> Sub<&Self> for Pos<T>
|
impl<T> Sub<&Self> for Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
type Output = Pos<T>;
|
type Output = Pos<T>;
|
||||||
fn sub(self, rhs: &Self) -> Self::Output {
|
fn sub(self, rhs: &Self) -> Self::Output {
|
||||||
|
|
@ -168,7 +202,7 @@ where
|
||||||
|
|
||||||
impl<T> Sub for &Pos<T>
|
impl<T> Sub for &Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
type Output = Pos<T>;
|
type Output = Pos<T>;
|
||||||
fn sub(self, rhs: &Pos<T>) -> Self::Output {
|
fn sub(self, rhs: &Pos<T>) -> Self::Output {
|
||||||
|
|
@ -178,7 +212,7 @@ where
|
||||||
|
|
||||||
impl<T> Sub<Pos<T>> for &Pos<T>
|
impl<T> Sub<Pos<T>> for &Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
type Output = Pos<T>;
|
type Output = Pos<T>;
|
||||||
fn sub(self, rhs: Pos<T>) -> Self::Output {
|
fn sub(self, rhs: Pos<T>) -> Self::Output {
|
||||||
|
|
@ -188,7 +222,7 @@ where
|
||||||
|
|
||||||
impl<T> Mul<T> for Pos<T>
|
impl<T> Mul<T> for Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn mul(self, rhs: T) -> Self::Output {
|
fn mul(self, rhs: T) -> Self::Output {
|
||||||
|
|
@ -198,7 +232,7 @@ where
|
||||||
|
|
||||||
impl<T> Mul<T> for &Pos<T>
|
impl<T> Mul<T> for &Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
type Output = Pos<T>;
|
type Output = Pos<T>;
|
||||||
fn mul(self, rhs: T) -> Self::Output {
|
fn mul(self, rhs: T) -> Self::Output {
|
||||||
|
|
@ -208,7 +242,7 @@ where
|
||||||
|
|
||||||
impl<T> Mul<&T> for Pos<T>
|
impl<T> Mul<&T> for Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
type Output = Pos<T>;
|
type Output = Pos<T>;
|
||||||
fn mul(self, rhs: &T) -> Self::Output {
|
fn mul(self, rhs: &T) -> Self::Output {
|
||||||
|
|
@ -218,7 +252,7 @@ where
|
||||||
|
|
||||||
impl<T> Mul<&T> for &Pos<T>
|
impl<T> Mul<&T> for &Pos<T>
|
||||||
where
|
where
|
||||||
T: Number,
|
T: Num + Copy,
|
||||||
{
|
{
|
||||||
type Output = Pos<T>;
|
type Output = Pos<T>;
|
||||||
fn mul(self, rhs: &T) -> Self::Output {
|
fn mul(self, rhs: &T) -> Self::Output {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ pub enum Turn {
|
||||||
use Turn::*;
|
use Turn::*;
|
||||||
|
|
||||||
impl Turn {
|
impl Turn {
|
||||||
pub fn to_left(&self) -> Turn {
|
pub fn turn_left(&self) -> Turn {
|
||||||
match *self {
|
match *self {
|
||||||
Left => Back,
|
Left => Back,
|
||||||
Back => Right,
|
Back => Right,
|
||||||
|
|
@ -21,7 +21,7 @@ impl Turn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_right(&self) -> Turn {
|
pub fn turn_right(&self) -> Turn {
|
||||||
match *self {
|
match *self {
|
||||||
Left => Forward,
|
Left => Forward,
|
||||||
Back => Left,
|
Back => Left,
|
||||||
|
|
@ -30,7 +30,7 @@ impl Turn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_back(&self) -> Turn {
|
pub fn turn_back(&self) -> Turn {
|
||||||
match *self {
|
match *self {
|
||||||
Left => Right,
|
Left => Right,
|
||||||
Back => Forward,
|
Back => Forward,
|
||||||
|
|
@ -56,9 +56,9 @@ impl Add for Turn {
|
||||||
|
|
||||||
fn add(self, rhs: Turn) -> Self::Output {
|
fn add(self, rhs: Turn) -> Self::Output {
|
||||||
match rhs {
|
match rhs {
|
||||||
Left => self.to_left(),
|
Left => self.turn_left(),
|
||||||
Back => self.to_back(),
|
Back => self.turn_back(),
|
||||||
Right => self.to_right(),
|
Right => self.turn_right(),
|
||||||
Forward => self,
|
Forward => self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ impl DayTrait for Day {
|
||||||
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
||||||
let vector = Day::parse(lines)?;
|
let vector = Day::parse(lines)?;
|
||||||
let max = vector.iter().max().ok_or(CalorieError::Empty)?;
|
let max = vector.iter().max().ok_or(CalorieError::Empty)?;
|
||||||
Ok(ResultType::IntResult(*max))
|
Ok(ResultType::Integer(*max))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
||||||
let vector = Day::parse(lines)?;
|
let vector = Day::parse(lines)?;
|
||||||
let sum = vector.iter().sorted_by(|a, b| Ord::cmp(b, a)).take(3).sum();
|
let sum = vector.iter().sorted_by(|a, b| Ord::cmp(b, a)).take(3).sum();
|
||||||
Ok(ResultType::IntResult(sum))
|
Ok(ResultType::Integer(sum))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ impl Day {
|
||||||
.iter()
|
.iter()
|
||||||
.batching(|it| {
|
.batching(|it| {
|
||||||
let result = it
|
let result = it
|
||||||
.take_while(|line| line.len() != 0)
|
.take_while(|line| !line.is_empty())
|
||||||
.map(|line| line.parse::<i64>())
|
.map(|line| line.parse::<i64>())
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
.map(|lst: _| lst.iter().sum::<i64>());
|
.map(|lst: _| lst.iter().sum::<i64>());
|
||||||
|
|
@ -64,7 +64,7 @@ mod test {
|
||||||
fn test_part1() -> Result<()> {
|
fn test_part1() -> Result<()> {
|
||||||
let day = Day {};
|
let day = Day {};
|
||||||
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
||||||
let expected = ResultType::IntResult(24_000);
|
let expected = ResultType::Integer(24_000);
|
||||||
let result = day.part1(&lines)?;
|
let result = day.part1(&lines)?;
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
|
@ -75,7 +75,7 @@ mod test {
|
||||||
fn test_part2() -> Result<()> {
|
fn test_part2() -> Result<()> {
|
||||||
let day = Day {};
|
let day = Day {};
|
||||||
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
||||||
let expected = ResultType::IntResult(45_000);
|
let expected = ResultType::Integer(45_000);
|
||||||
let result = day.part2(&lines)?;
|
let result = day.part2(&lines)?;
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,25 +15,25 @@ impl DayTrait for Day {
|
||||||
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
||||||
let sum = lines
|
let sum = lines
|
||||||
.iter()
|
.iter()
|
||||||
.map(|line| RPS::parse_line(&line))
|
.map(|line| Rps::parse_line(line))
|
||||||
.collect::<Result<Vec<_>, _>>()?
|
.collect::<Result<Vec<_>, _>>()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(first, second)| second.asses_pair(&first))
|
.map(|(first, second)| second.asses_pair(&first))
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
Ok(ResultType::IntResult(sum))
|
Ok(ResultType::Integer(sum))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
||||||
let sum = lines
|
let sum = lines
|
||||||
.iter()
|
.iter()
|
||||||
.map(|line| Strategy::parse_line(&line))
|
.map(|line| Strategy::parse_line(line))
|
||||||
.collect::<Result<Vec<_>, _>>()?
|
.collect::<Result<Vec<_>, _>>()?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(first, second)| second.fullfill(&first).asses_pair(&first))
|
.map(|(first, second)| second.fullfill(&first).asses_pair(&first))
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
Ok(ResultType::IntResult(sum))
|
Ok(ResultType::Integer(sum))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,29 +47,29 @@ enum RPSError {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
enum RPS {
|
enum Rps {
|
||||||
Rock,
|
Rock,
|
||||||
Paper,
|
Paper,
|
||||||
Scissors,
|
Scissors,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RPS {
|
impl Rps {
|
||||||
pub fn parse_line(line: &str) -> Result<(Self, Self), RPSError> {
|
pub fn parse_line(line: &str) -> Result<(Self, Self), RPSError> {
|
||||||
let mut parts = line.split(" ");
|
let mut parts = line.split(' ');
|
||||||
let (Some(first), Some(second)) = (parts.next(), parts.next()) else {
|
let (Some(first), Some(second)) = (parts.next(), parts.next()) else {
|
||||||
Err(RPSError::IllegalLine(line.to_owned()))?
|
Err(RPSError::IllegalLine(line.to_owned()))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let first = RPS::try_from(first)?;
|
let first = Rps::try_from(first)?;
|
||||||
let second = RPS::try_from(second)?;
|
let second = Rps::try_from(second)?;
|
||||||
Ok((first, second))
|
Ok((first, second))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value(&self) -> i64 {
|
pub fn value(&self) -> i64 {
|
||||||
match self {
|
match self {
|
||||||
RPS::Rock => 1,
|
Rps::Rock => 1,
|
||||||
RPS::Paper => 2,
|
Rps::Paper => 2,
|
||||||
RPS::Scissors => 3,
|
Rps::Scissors => 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,13 +84,13 @@ impl RPS {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for RPS {
|
impl PartialOrd for Rps {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(RPS::Rock, RPS::Paper) | (RPS::Paper, RPS::Scissors) | (RPS::Scissors, RPS::Rock) => {
|
(Rps::Rock, Rps::Paper) | (Rps::Paper, Rps::Scissors) | (Rps::Scissors, Rps::Rock) => {
|
||||||
Some(Ordering::Less)
|
Some(Ordering::Less)
|
||||||
}
|
}
|
||||||
(RPS::Rock, RPS::Scissors) | (RPS::Paper, RPS::Rock) | (RPS::Scissors, RPS::Paper) => {
|
(Rps::Rock, Rps::Scissors) | (Rps::Paper, Rps::Rock) | (Rps::Scissors, Rps::Paper) => {
|
||||||
Some(Ordering::Greater)
|
Some(Ordering::Greater)
|
||||||
}
|
}
|
||||||
_ => Some(Ordering::Equal),
|
_ => Some(Ordering::Equal),
|
||||||
|
|
@ -98,14 +98,14 @@ impl PartialOrd for RPS {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<&str> for RPS {
|
impl TryFrom<&str> for Rps {
|
||||||
type Error = RPSError;
|
type Error = RPSError;
|
||||||
|
|
||||||
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
|
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
"A" | "X" => Ok(RPS::Rock),
|
"A" | "X" => Ok(Rps::Rock),
|
||||||
"B" | "Y" => Ok(RPS::Paper),
|
"B" | "Y" => Ok(Rps::Paper),
|
||||||
"C" | "Z" => Ok(RPS::Scissors),
|
"C" | "Z" => Ok(Rps::Scissors),
|
||||||
_ => Err(RPSError::ParseError(value.to_owned())),
|
_ => Err(RPSError::ParseError(value.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -118,23 +118,23 @@ enum Strategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Strategy {
|
impl Strategy {
|
||||||
pub fn parse_line(line: &str) -> Result<(RPS, Self), RPSError> {
|
pub fn parse_line(line: &str) -> Result<(Rps, Self), RPSError> {
|
||||||
let mut parts = line.split(" ");
|
let mut parts = line.split(' ');
|
||||||
let (Some(first), Some(second)) = (parts.next(), parts.next()) else {
|
let (Some(first), Some(second)) = (parts.next(), parts.next()) else {
|
||||||
Err(RPSError::IllegalLine(line.to_owned()))?
|
Err(RPSError::IllegalLine(line.to_owned()))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let first = RPS::try_from(first)?;
|
let first = Rps::try_from(first)?;
|
||||||
let second = Strategy::try_from(second)?;
|
let second = Strategy::try_from(second)?;
|
||||||
Ok((first, second))
|
Ok((first, second))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fullfill(&self, other: &RPS) -> RPS {
|
pub fn fullfill(&self, other: &Rps) -> Rps {
|
||||||
match (other, self) {
|
match (other, self) {
|
||||||
(_, Strategy::Draw) => *other,
|
(_, Strategy::Draw) => *other,
|
||||||
(RPS::Rock, Strategy::Win) | (RPS::Scissors, Strategy::Loose) => RPS::Paper,
|
(Rps::Rock, Strategy::Win) | (Rps::Scissors, Strategy::Loose) => Rps::Paper,
|
||||||
(RPS::Paper, Strategy::Win) | (RPS::Rock, Strategy::Loose) => RPS::Scissors,
|
(Rps::Paper, Strategy::Win) | (Rps::Rock, Strategy::Loose) => Rps::Scissors,
|
||||||
(RPS::Scissors, Strategy::Win) | (RPS::Paper, Strategy::Loose) => RPS::Rock,
|
(Rps::Scissors, Strategy::Win) | (Rps::Paper, Strategy::Loose) => Rps::Rock,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,8 +161,8 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse() -> Result<()> {
|
fn test_parse() -> Result<()> {
|
||||||
let input = "A Y";
|
let input = "A Y";
|
||||||
let expected = (RPS::Rock, RPS::Paper);
|
let expected = (Rps::Rock, Rps::Paper);
|
||||||
let result = RPS::parse_line(input)?;
|
let result = Rps::parse_line(input)?;
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -170,8 +170,8 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_assess() -> Result<()> {
|
fn test_assess() -> Result<()> {
|
||||||
let first = RPS::Scissors;
|
let first = Rps::Scissors;
|
||||||
let second = RPS::Paper;
|
let second = Rps::Paper;
|
||||||
let expected = 9;
|
let expected = 9;
|
||||||
let result = first.asses_pair(&second);
|
let result = first.asses_pair(&second);
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
@ -183,7 +183,7 @@ mod test {
|
||||||
fn test_part1() -> Result<()> {
|
fn test_part1() -> Result<()> {
|
||||||
let day = Day {};
|
let day = Day {};
|
||||||
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
||||||
let expected = ResultType::IntResult(15);
|
let expected = ResultType::Integer(15);
|
||||||
let result = day.part1(&lines)?;
|
let result = day.part1(&lines)?;
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
|
@ -193,7 +193,7 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_strategy() -> Result<()> {
|
fn test_parse_strategy() -> Result<()> {
|
||||||
let input = "A Y";
|
let input = "A Y";
|
||||||
let expected = (RPS::Rock, Strategy::Draw);
|
let expected = (Rps::Rock, Strategy::Draw);
|
||||||
let result = Strategy::parse_line(input)?;
|
let result = Strategy::parse_line(input)?;
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
|
@ -202,9 +202,9 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_assess_stragety() -> Result<()> {
|
fn test_assess_stragety() -> Result<()> {
|
||||||
let first = RPS::Scissors;
|
let first = Rps::Scissors;
|
||||||
let second = Strategy::Win;
|
let second = Strategy::Win;
|
||||||
let expected = RPS::Rock;
|
let expected = Rps::Rock;
|
||||||
let result = second.fullfill(&first);
|
let result = second.fullfill(&first);
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
|
@ -215,7 +215,7 @@ mod test {
|
||||||
fn test_part2() -> Result<()> {
|
fn test_part2() -> Result<()> {
|
||||||
let day = Day {};
|
let day = Day {};
|
||||||
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
||||||
let expected = ResultType::NoResult;
|
let expected = ResultType::Nothing;
|
||||||
let result = day.part2(&lines)?;
|
let result = day.part2(&lines)?;
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,11 @@ impl DayTrait for Day {
|
||||||
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
||||||
let sum = lines
|
let sum = lines
|
||||||
.iter()
|
.iter()
|
||||||
.map(|line| find_double(&line))
|
.map(|line| find_double(line))
|
||||||
.map_ok(priority)
|
.map_ok(priority)
|
||||||
.flatten_ok()
|
.flatten_ok()
|
||||||
.fold_ok(0, |a, b| a + b)?;
|
.fold_ok(0, |a, b| a + b)?;
|
||||||
Ok(ResultType::IntResult(sum))
|
Ok(ResultType::Integer(sum))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
||||||
|
|
@ -30,7 +30,7 @@ impl DayTrait for Day {
|
||||||
.map_ok(priority)
|
.map_ok(priority)
|
||||||
.flatten_ok()
|
.flatten_ok()
|
||||||
.fold_ok(0, |a, b| a + b)?;
|
.fold_ok(0, |a, b| a + b)?;
|
||||||
Ok(ResultType::IntResult(sum))
|
Ok(ResultType::Integer(sum))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,7 +71,7 @@ fn find_double(content: &str) -> Result<char, RucksackError> {
|
||||||
Err(RucksackError::NoDoubleFound)?
|
Err(RucksackError::NoDoubleFound)?
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_badge<'a>(elves: &[&String]) -> Result<char, RucksackError> {
|
fn find_badge(elves: &[&String]) -> Result<char, RucksackError> {
|
||||||
if elves.len() < 2 {
|
if elves.len() < 2 {
|
||||||
return Err(RucksackError::NeedAtLeastTwo);
|
return Err(RucksackError::NeedAtLeastTwo);
|
||||||
};
|
};
|
||||||
|
|
@ -109,7 +109,7 @@ mod test {
|
||||||
fn test_part1() -> Result<()> {
|
fn test_part1() -> Result<()> {
|
||||||
let day = Day {};
|
let day = Day {};
|
||||||
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
||||||
let expected = ResultType::IntResult(157);
|
let expected = ResultType::Integer(157);
|
||||||
let result = day.part1(&lines)?;
|
let result = day.part1(&lines)?;
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
|
@ -120,7 +120,7 @@ mod test {
|
||||||
fn test_part2() -> Result<()> {
|
fn test_part2() -> Result<()> {
|
||||||
let day = Day {};
|
let day = Day {};
|
||||||
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
||||||
let expected = ResultType::IntResult(70);
|
let expected = ResultType::Integer(70);
|
||||||
let result = day.part2(&lines)?;
|
let result = day.part2(&lines)?;
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,19 +15,19 @@ impl DayTrait for Day {
|
||||||
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
||||||
let sum = lines
|
let sum = lines
|
||||||
.iter()
|
.iter()
|
||||||
.map(|line| parse(&line))
|
.map(|line| parse(line))
|
||||||
.filter_ok(fully_contained)
|
.filter_ok(fully_contained)
|
||||||
.fold_ok(0i64, |a, _| a + 1)?;
|
.fold_ok(0i64, |a, _| a + 1)?;
|
||||||
Ok(ResultType::IntResult(sum))
|
Ok(ResultType::Integer(sum))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
|
||||||
let sum = lines
|
let sum = lines
|
||||||
.iter()
|
.iter()
|
||||||
.map(|line| parse(&line))
|
.map(|line| parse(line))
|
||||||
.filter_ok(overlaps)
|
.filter_ok(overlaps)
|
||||||
.fold_ok(0i64, |a, _| a + 1)?;
|
.fold_ok(0i64, |a, _| a + 1)?;
|
||||||
Ok(ResultType::IntResult(sum))
|
Ok(ResultType::Integer(sum))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,7 +94,7 @@ mod test {
|
||||||
fn test_part1() -> Result<()> {
|
fn test_part1() -> Result<()> {
|
||||||
let day = Day {};
|
let day = Day {};
|
||||||
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
||||||
let expected = ResultType::IntResult(2);
|
let expected = ResultType::Integer(2);
|
||||||
let result = day.part1(&lines)?;
|
let result = day.part1(&lines)?;
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ mod test {
|
||||||
fn test_part2() -> Result<()> {
|
fn test_part2() -> Result<()> {
|
||||||
let day = Day {};
|
let day = Day {};
|
||||||
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
let lines = read_lines(day.get_day_number(), "example01.txt")?;
|
||||||
let expected = ResultType::IntResult(4);
|
let expected = ResultType::Integer(4);
|
||||||
let result = day.part2(&lines)?;
|
let result = day.part2(&lines)?;
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ use anyhow::Result;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum ResultType {
|
pub enum ResultType {
|
||||||
IntResult(i64),
|
Integer(i64),
|
||||||
StringResult(String),
|
String(String),
|
||||||
LinesResult(Vec<String>),
|
Lines(Vec<String>),
|
||||||
NoResult,
|
Nothing,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DayTrait {
|
pub trait DayTrait {
|
||||||
|
|
|
||||||
28
src/main.rs
28
src/main.rs
|
|
@ -11,9 +11,9 @@ use std::{
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
fn output(day: usize, part: usize, result: ResultType, time: Duration) -> () {
|
fn output(day: usize, part: usize, result: ResultType, time: Duration) {
|
||||||
match result {
|
match result {
|
||||||
ResultType::IntResult(value) => {
|
ResultType::Integer(value) => {
|
||||||
println!(
|
println!(
|
||||||
"Day {:02} part {}: {} ({})",
|
"Day {:02} part {}: {} ({})",
|
||||||
day,
|
day,
|
||||||
|
|
@ -22,7 +22,7 @@ fn output(day: usize, part: usize, result: ResultType, time: Duration) -> () {
|
||||||
time.as_secs_f64()
|
time.as_secs_f64()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ResultType::StringResult(value) => {
|
ResultType::String(value) => {
|
||||||
println!(
|
println!(
|
||||||
"Day {:02} part {}: {} ({})",
|
"Day {:02} part {}: {} ({})",
|
||||||
day,
|
day,
|
||||||
|
|
@ -31,7 +31,7 @@ fn output(day: usize, part: usize, result: ResultType, time: Duration) -> () {
|
||||||
time.as_secs_f32()
|
time.as_secs_f32()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ResultType::LinesResult(value) => {
|
ResultType::Lines(value) => {
|
||||||
println!(
|
println!(
|
||||||
"Day {:02} part {}: {} ({})",
|
"Day {:02} part {}: {} ({})",
|
||||||
day,
|
day,
|
||||||
|
|
@ -40,14 +40,14 @@ fn output(day: usize, part: usize, result: ResultType, time: Duration) -> () {
|
||||||
time.as_secs_f32()
|
time.as_secs_f32()
|
||||||
);
|
);
|
||||||
for line in &value[1..] {
|
for line in &value[1..] {
|
||||||
println!(" part : {}", line);
|
println!(" part : {line}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResultType::NoResult => {}
|
ResultType::Nothing => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_part(day: &Box<dyn DayTrait>, is_part1: bool, lines: &[String]) -> Result<Duration> {
|
fn run_part(day: &dyn DayTrait, is_part1: bool, lines: &[String]) -> Result<Duration> {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let result = if is_part1 {
|
let result = if is_part1 {
|
||||||
day.part1(lines)?
|
day.part1(lines)?
|
||||||
|
|
@ -55,7 +55,7 @@ fn run_part(day: &Box<dyn DayTrait>, is_part1: bool, lines: &[String]) -> Result
|
||||||
day.part2(lines)?
|
day.part2(lines)?
|
||||||
};
|
};
|
||||||
|
|
||||||
if matches!(result, ResultType::NoResult) {
|
if matches!(result, ResultType::Nothing) {
|
||||||
Ok(Duration::ZERO)
|
Ok(Duration::ZERO)
|
||||||
} else {
|
} else {
|
||||||
let elapsed = now.elapsed();
|
let elapsed = now.elapsed();
|
||||||
|
|
@ -69,7 +69,7 @@ fn run_part(day: &Box<dyn DayTrait>, is_part1: bool, lines: &[String]) -> Result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(day: &Box<dyn DayTrait>, part1: bool, part2: bool) -> Result<Duration> {
|
fn run(day: &dyn DayTrait, part1: bool, part2: bool) -> Result<Duration> {
|
||||||
let lines = read_lines(day.get_day_number(), "input.txt")?;
|
let lines = read_lines(day.get_day_number(), "input.txt")?;
|
||||||
let elapsed1 = if part1 {
|
let elapsed1 = if part1 {
|
||||||
run_part(day, true, &lines)?
|
run_part(day, true, &lines)?
|
||||||
|
|
@ -99,25 +99,25 @@ fn run_on_parameters(params: &[String]) -> Result<()> {
|
||||||
0 => {
|
0 => {
|
||||||
let mut runtime = Duration::ZERO;
|
let mut runtime = Duration::ZERO;
|
||||||
for day in day_provider::get_all_days() {
|
for day in day_provider::get_all_days() {
|
||||||
runtime += run(&day, true, true)?;
|
runtime += run(day.as_ref(), true, true)?;
|
||||||
}
|
}
|
||||||
println!();
|
println!();
|
||||||
println!("Runtime: {}", runtime.as_secs_f32());
|
println!("Runtime: {}", runtime.as_secs_f32());
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
let mut parts = params[0].split("/");
|
let mut parts = params[0].split('/');
|
||||||
if let Some(day_str) = parts.next() {
|
if let Some(day_str) = parts.next() {
|
||||||
let day_number = day_str.parse::<usize>()?;
|
let day_number = day_str.parse::<usize>()?;
|
||||||
let day = day_provider::get_day(day_number)?;
|
let day = day_provider::get_day(day_number)?;
|
||||||
|
|
||||||
if let Some(part_str) = parts.next() {
|
if let Some(part_str) = parts.next() {
|
||||||
match part_str.parse::<usize>()? {
|
match part_str.parse::<usize>()? {
|
||||||
1 => run(&day, true, false)?,
|
1 => run(day.as_ref(), true, false)?,
|
||||||
2 => run(&day, false, true)?,
|
2 => run(day.as_ref(), false, true)?,
|
||||||
p => Err(ParamError::UnknownPart(p))?,
|
p => Err(ParamError::UnknownPart(p))?,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
let runtime = run(&day, true, true)?;
|
let runtime = run(day.as_ref(), true, true)?;
|
||||||
println!("Runtime: {}", runtime.as_secs_f32());
|
println!("Runtime: {}", runtime.as_secs_f32());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue