applied clippy

This commit is contained in:
Ruediger Ludwig 2023-01-29 19:12:22 +01:00
parent 33eb92e9d1
commit 4e08117ed0
16 changed files with 205 additions and 504 deletions

View file

@ -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"

View file

@ -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();
} }
} }

View file

@ -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())

View file

@ -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,
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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
}
}

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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,
} }
} }

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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 {

View file

@ -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());
} }
} }