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

@ -1,12 +1,14 @@
#![allow(dead_code)]
use std::fmt::Display;
use super::{number::Number, pos::Pos};
use num_traits::{Num, NumAssignOps};
use super::pos::Pos;
#[derive(Debug, Clone, Copy, Default)]
pub struct Area<T>
where
T: Number,
T: Num,
{
lower_left: Pos<T>,
upper_right: Pos<T>,
@ -14,7 +16,7 @@ where
impl<T> Area<T>
where
T: Number + Ord,
T: Num + Ord + Copy,
{
pub fn new(p1: Pos<T>, p2: Pos<T>) -> Area<T> {
Area {
@ -22,7 +24,12 @@ where
upper_right: p1.max_components(&p2),
}
}
}
impl<T> Area<T>
where
T: Num + Ord + Copy,
{
pub fn extend(&self, pos: Pos<T>) -> Area<T> {
if self.contains(pos) {
return *self;
@ -33,7 +40,6 @@ where
upper_right: self.upper_right.max_components(&pos),
}
}
pub fn get_lower_left(&self) -> Pos<T> {
self.lower_left
}
@ -52,7 +58,7 @@ where
impl<'a, T> Area<T>
where
T: Number + Ord + 'a,
T: Num + Ord + 'a + Copy,
{
pub fn from_iterator<I>(mut iter: I) -> Option<Self>
where
@ -60,7 +66,7 @@ where
{
let first = *iter.next()?;
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))
@ -69,21 +75,21 @@ where
impl<T> Area<T>
where
T: Number,
T: Num + Copy,
{
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)]
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>
where
T: Number,
T: Num + Copy,
{
#[allow(dead_code)]
pub fn area(&self) -> T {
@ -93,7 +99,7 @@ where
impl<T> Display for Area<T>
where
T: Number + Display,
T: Num + Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[{}-{}]", self.lower_left, self.upper_right)
@ -102,7 +108,7 @@ where
impl<T> Area<T>
where
T: Number,
T: Num + Copy,
{
pub fn cells(&self, ascending: bool) -> CellIterator<'_, T> {
CellIterator::new(self, ascending)
@ -116,7 +122,7 @@ where
#[derive(Debug)]
pub struct RowIterator<'a, T>
where
T: Number,
T: Num + Copy,
{
area: &'a Area<T>,
row: T,
@ -125,7 +131,7 @@ where
impl<'a, T> RowIterator<'a, T>
where
T: Number,
T: Num + Copy,
{
fn new(area: &'a Area<T>, ascending: bool) -> RowIterator<'a, T> {
RowIterator {
@ -142,7 +148,7 @@ where
impl<'a, T> Iterator for RowIterator<'a, T>
where
T: Number,
T: Num + Ord + NumAssignOps + Copy,
{
type Item = Row<'a, T>;
@ -155,9 +161,9 @@ where
row: self.row,
};
if self.ascending {
self.row += T::ONE;
self.row += T::one();
} else {
self.row -= T::ONE;
self.row -= T::one();
}
Some(row)
} else {
@ -169,7 +175,7 @@ where
#[derive(Debug)]
pub struct Row<'a, T>
where
T: Number,
T: Num,
{
area: &'a Area<T>,
row: T,
@ -177,7 +183,7 @@ where
impl<'a, T> Row<'a, T>
where
T: Number,
T: Num + Copy,
{
pub fn cols(&self, ascending: bool) -> ColIterator<'_, T> {
ColIterator {
@ -196,7 +202,7 @@ where
#[derive(Debug)]
pub struct ColIterator<'a, T>
where
T: Number,
T: Num,
{
area: &'a Area<T>,
row: T,
@ -206,7 +212,7 @@ where
impl<'a, T> Iterator for ColIterator<'a, T>
where
T: Number,
T: Num + Ord + NumAssignOps + Copy,
{
type Item = Pos<T>;
fn next(&mut self) -> Option<Self::Item> {
@ -215,10 +221,10 @@ where
{
let pos = Pos::new(self.col, self.row);
if self.ascending {
self.col += T::ONE
self.col += T::one();
} else {
self.col -= T::ONE
};
self.col -= T::one();
}
Some(pos)
} else {
None
@ -229,7 +235,7 @@ where
#[derive(Debug)]
pub struct CellIterator<'a, T>
where
T: Number,
T: Num,
{
area: &'a Area<T>,
row: T,
@ -239,7 +245,7 @@ where
impl<'a, T> CellIterator<'a, T>
where
T: Number,
T: Num + Copy,
{
pub fn new(area: &'a Area<T>, ascending: bool) -> CellIterator<'a, T> {
let (col, row) = if ascending {
@ -258,7 +264,7 @@ where
impl<'a, T> Iterator for CellIterator<'a, T>
where
T: Number,
T: Num + Ord + NumAssignOps + Copy,
{
type Item = Pos<T>;
@ -268,15 +274,15 @@ where
{
let pos = Pos::new(self.col, self.row);
if self.ascending {
self.col += T::ONE;
self.col += T::one();
if self.col > self.area.upper_right.x() {
self.row += T::ONE;
self.row += T::one();
self.col = self.area.lower_left.x();
}
} else {
self.col -= T::ONE;
self.col -= T::one();
if self.col < self.area.lower_left.x() {
self.row -= T::ONE;
self.row -= T::one();
self.col = self.area.upper_right.x();
}
}

View file

@ -2,7 +2,7 @@ use itertools::Itertools;
use std::{fs, io};
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>> {
@ -15,7 +15,7 @@ pub fn read_lines(day_num: usize, file: &str) -> io::Result<Vec<String>> {
| itertools::Position::Middle(line)
| itertools::Position::Only(line) => Some(line.to_owned()),
itertools::Position::Last(line) => {
if line.len() == 0 {
if line.is_empty() {
None
} else {
Some(line.to_owned())

View file

@ -74,21 +74,3 @@ pub fn zip7<A, B, C, D, E, F, G>(
_ => 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)]
use thiserror::Error;
use super::number::Number;
use num_traits::{Euclid, Num};
#[derive(Error, Debug)]
pub enum MathError {
@ -17,35 +17,36 @@ pub enum MathError {
fn non_zero_gcd<T>(mut a: T, mut b: T) -> T
where
T: Number,
T: Num + Ord + Copy,
{
while b != T::ZERO {
while !b.is_zero() {
let t = a % b;
a = b;
b = t;
}
a.abs()
a
}
pub fn gcd<T>(a: T, b: T) -> T
where
T: Number,
T: Num + Ord + Copy,
{
if a == T::ZERO {
b.abs()
} else if b == T::ZERO {
a.abs()
assert!(a >= T::zero());
assert!(b >= T::zero());
if a.is_zero() {
b
} else if b.is_zero() {
a
} else {
non_zero_gcd(a, b)
}
}
pub fn lcm<T>(a: T, b: T) -> T
where
T: Number,
T: Num + Ord + Copy,
{
if a == T::ZERO || b == T::ZERO {
T::ZERO
if a.is_zero() || b.is_zero() {
T::zero()
} else {
a * b / non_zero_gcd(a, b)
}
@ -53,64 +54,20 @@ where
pub fn modulus_inv<T>(num: T, modulo: T) -> Option<T>
where
T: Number,
T: Num + Euclid + Copy,
{
let num = num.rem_euclid(modulo);
let mut s = (T::ZERO, T::ONE);
let num = num.rem_euclid(&modulo);
let mut s = (T::zero(), T::one());
let mut r = (modulo, num);
while r.0 != T::ZERO {
while !r.0.is_zero() {
let q = r.1 / r.0;
r = (r.1 - q * r.0, r.0);
s = (s.1 - q * s.0, s.0);
}
if r.1 != T::ONE {
if !r.1.is_one() {
None
} else {
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)
Some(s.1.rem_euclid(&modulo))
}
}
@ -131,29 +88,6 @@ mod tests {
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]
fn test_inverse_modulo() {
let num = 3;

View file

@ -3,7 +3,5 @@ pub mod direction;
pub mod file;
pub mod helper;
pub mod math;
pub mod number;
pub mod permutations;
pub mod pos;
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::ops::{Add, Mul, Sub};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Pos<T>(T, T)
where
T: Number;
T: Num;
impl<T> Pos<T>
where
T: Number,
T: Num,
{
pub fn new(x: T, y: T) -> Pos<T> {
Pos(x, y)
}
}
impl<T> Pos<T>
where
T: Num + Copy,
{
pub fn x(&self) -> T {
self.0
}
@ -22,7 +29,47 @@ where
pub fn y(&self) -> T {
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 {
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 {
Self(self.0.min(other.0), self.1.min(other.1))
}
}
impl<T> Pos<T>
where
T: Num + Signed,
{
pub fn abs(&self) -> T {
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>
where
T: Number + fmt::Display,
T: Num + fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}, {})", self.0, self.1)
@ -65,7 +99,7 @@ where
impl<T> Add for Pos<T>
where
T: Number,
T: Num,
{
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
@ -75,7 +109,7 @@ where
impl<T> Add for &Pos<T>
where
T: Number,
T: Num + Copy,
{
type Output = <Pos<T> as Add<Pos<T>>>::Output;
@ -86,7 +120,7 @@ where
impl<T> Add<&Pos<T>> for Pos<T>
where
T: Number,
T: Num + Copy,
{
type Output = <Pos<T> as Add<Pos<T>>>::Output;
fn add(self, rhs: &Self) -> Self::Output {
@ -96,7 +130,7 @@ where
impl<T> Add<Pos<T>> for &Pos<T>
where
T: Number,
T: Num + Copy,
{
type Output = <Pos<T> as Add<Pos<T>>>::Output;
fn add(self, rhs: Pos<T>) -> Self::Output {
@ -106,7 +140,7 @@ where
impl<T> Add<(T, T)> for Pos<T>
where
T: Number,
T: Num,
{
type Output = Self;
fn add(self, rhs: (T, T)) -> Self::Output {
@ -148,7 +182,7 @@ impl Add<Direction> for &Pos<i32> {
impl<T> Sub for Pos<T>
where
T: Number,
T: Num,
{
type Output = Pos<T>;
fn sub(self, rhs: Self) -> Self::Output {
@ -158,7 +192,7 @@ where
impl<T> Sub<&Self> for Pos<T>
where
T: Number,
T: Num + Copy,
{
type Output = Pos<T>;
fn sub(self, rhs: &Self) -> Self::Output {
@ -168,7 +202,7 @@ where
impl<T> Sub for &Pos<T>
where
T: Number,
T: Num + Copy,
{
type Output = Pos<T>;
fn sub(self, rhs: &Pos<T>) -> Self::Output {
@ -178,7 +212,7 @@ where
impl<T> Sub<Pos<T>> for &Pos<T>
where
T: Number,
T: Num + Copy,
{
type Output = Pos<T>;
fn sub(self, rhs: Pos<T>) -> Self::Output {
@ -188,7 +222,7 @@ where
impl<T> Mul<T> for Pos<T>
where
T: Number,
T: Num + Copy,
{
type Output = Self;
fn mul(self, rhs: T) -> Self::Output {
@ -198,7 +232,7 @@ where
impl<T> Mul<T> for &Pos<T>
where
T: Number,
T: Num + Copy,
{
type Output = Pos<T>;
fn mul(self, rhs: T) -> Self::Output {
@ -208,7 +242,7 @@ where
impl<T> Mul<&T> for Pos<T>
where
T: Number,
T: Num + Copy,
{
type Output = Pos<T>;
fn mul(self, rhs: &T) -> Self::Output {
@ -218,7 +252,7 @@ where
impl<T> Mul<&T> for &Pos<T>
where
T: Number,
T: Num + Copy,
{
type Output = Pos<T>;
fn mul(self, rhs: &T) -> Self::Output {

View file

@ -12,7 +12,7 @@ pub enum Turn {
use Turn::*;
impl Turn {
pub fn to_left(&self) -> Turn {
pub fn turn_left(&self) -> Turn {
match *self {
Left => Back,
Back => Right,
@ -21,7 +21,7 @@ impl Turn {
}
}
pub fn to_right(&self) -> Turn {
pub fn turn_right(&self) -> Turn {
match *self {
Left => Forward,
Back => Left,
@ -30,7 +30,7 @@ impl Turn {
}
}
pub fn to_back(&self) -> Turn {
pub fn turn_back(&self) -> Turn {
match *self {
Left => Right,
Back => Forward,
@ -56,9 +56,9 @@ impl Add for Turn {
fn add(self, rhs: Turn) -> Self::Output {
match rhs {
Left => self.to_left(),
Back => self.to_back(),
Right => self.to_right(),
Left => self.turn_left(),
Back => self.turn_back(),
Right => self.turn_right(),
Forward => self,
}
}

View file

@ -16,13 +16,13 @@ impl DayTrait for Day {
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
let vector = Day::parse(lines)?;
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> {
let vector = Day::parse(lines)?;
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()
.batching(|it| {
let result = it
.take_while(|line| line.len() != 0)
.take_while(|line| !line.is_empty())
.map(|line| line.parse::<i64>())
.collect::<Result<Vec<_>, _>>()
.map(|lst: _| lst.iter().sum::<i64>());
@ -64,7 +64,7 @@ mod test {
fn test_part1() -> Result<()> {
let day = Day {};
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)?;
assert_eq!(result, expected);
@ -75,7 +75,7 @@ mod test {
fn test_part2() -> Result<()> {
let day = Day {};
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)?;
assert_eq!(result, expected);

View file

@ -15,25 +15,25 @@ impl DayTrait for Day {
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
let sum = lines
.iter()
.map(|line| RPS::parse_line(&line))
.map(|line| Rps::parse_line(line))
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.map(|(first, second)| second.asses_pair(&first))
.sum();
Ok(ResultType::IntResult(sum))
Ok(ResultType::Integer(sum))
}
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
let sum = lines
.iter()
.map(|line| Strategy::parse_line(&line))
.map(|line| Strategy::parse_line(line))
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.map(|(first, second)| second.fullfill(&first).asses_pair(&first))
.sum();
Ok(ResultType::IntResult(sum))
Ok(ResultType::Integer(sum))
}
}
@ -47,29 +47,29 @@ enum RPSError {
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
enum RPS {
enum Rps {
Rock,
Paper,
Scissors,
}
impl RPS {
impl Rps {
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 {
Err(RPSError::IllegalLine(line.to_owned()))?
};
let first = RPS::try_from(first)?;
let second = RPS::try_from(second)?;
let first = Rps::try_from(first)?;
let second = Rps::try_from(second)?;
Ok((first, second))
}
pub fn value(&self) -> i64 {
match self {
RPS::Rock => 1,
RPS::Paper => 2,
RPS::Scissors => 3,
Rps::Rock => 1,
Rps::Paper => 2,
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> {
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)
}
(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::Equal),
@ -98,14 +98,14 @@ impl PartialOrd for RPS {
}
}
impl TryFrom<&str> for RPS {
impl TryFrom<&str> for Rps {
type Error = RPSError;
fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
match value {
"A" | "X" => Ok(RPS::Rock),
"B" | "Y" => Ok(RPS::Paper),
"C" | "Z" => Ok(RPS::Scissors),
"A" | "X" => Ok(Rps::Rock),
"B" | "Y" => Ok(Rps::Paper),
"C" | "Z" => Ok(Rps::Scissors),
_ => Err(RPSError::ParseError(value.to_owned())),
}
}
@ -118,23 +118,23 @@ enum Strategy {
}
impl Strategy {
pub fn parse_line(line: &str) -> Result<(RPS, Self), RPSError> {
let mut parts = line.split(" ");
pub fn parse_line(line: &str) -> Result<(Rps, Self), RPSError> {
let mut parts = line.split(' ');
let (Some(first), Some(second)) = (parts.next(), parts.next()) else {
Err(RPSError::IllegalLine(line.to_owned()))?
};
let first = RPS::try_from(first)?;
let first = Rps::try_from(first)?;
let second = Strategy::try_from(second)?;
Ok((first, second))
}
pub fn fullfill(&self, other: &RPS) -> RPS {
pub fn fullfill(&self, other: &Rps) -> Rps {
match (other, self) {
(_, Strategy::Draw) => *other,
(RPS::Rock, Strategy::Win) | (RPS::Scissors, Strategy::Loose) => RPS::Paper,
(RPS::Paper, Strategy::Win) | (RPS::Rock, Strategy::Loose) => RPS::Scissors,
(RPS::Scissors, Strategy::Win) | (RPS::Paper, Strategy::Loose) => RPS::Rock,
(Rps::Rock, Strategy::Win) | (Rps::Scissors, Strategy::Loose) => Rps::Paper,
(Rps::Paper, Strategy::Win) | (Rps::Rock, Strategy::Loose) => Rps::Scissors,
(Rps::Scissors, Strategy::Win) | (Rps::Paper, Strategy::Loose) => Rps::Rock,
}
}
}
@ -161,8 +161,8 @@ mod test {
#[test]
fn test_parse() -> Result<()> {
let input = "A Y";
let expected = (RPS::Rock, RPS::Paper);
let result = RPS::parse_line(input)?;
let expected = (Rps::Rock, Rps::Paper);
let result = Rps::parse_line(input)?;
assert_eq!(result, expected);
Ok(())
@ -170,8 +170,8 @@ mod test {
#[test]
fn test_assess() -> Result<()> {
let first = RPS::Scissors;
let second = RPS::Paper;
let first = Rps::Scissors;
let second = Rps::Paper;
let expected = 9;
let result = first.asses_pair(&second);
assert_eq!(result, expected);
@ -183,7 +183,7 @@ mod test {
fn test_part1() -> Result<()> {
let day = Day {};
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)?;
assert_eq!(result, expected);
@ -193,7 +193,7 @@ mod test {
#[test]
fn test_parse_strategy() -> Result<()> {
let input = "A Y";
let expected = (RPS::Rock, Strategy::Draw);
let expected = (Rps::Rock, Strategy::Draw);
let result = Strategy::parse_line(input)?;
assert_eq!(result, expected);
@ -202,9 +202,9 @@ mod test {
#[test]
fn test_assess_stragety() -> Result<()> {
let first = RPS::Scissors;
let first = Rps::Scissors;
let second = Strategy::Win;
let expected = RPS::Rock;
let expected = Rps::Rock;
let result = second.fullfill(&first);
assert_eq!(result, expected);
@ -215,7 +215,7 @@ mod test {
fn test_part2() -> Result<()> {
let day = Day {};
let lines = read_lines(day.get_day_number(), "example01.txt")?;
let expected = ResultType::NoResult;
let expected = ResultType::Nothing;
let result = day.part2(&lines)?;
assert_eq!(result, expected);

View file

@ -14,11 +14,11 @@ impl DayTrait for Day {
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
let sum = lines
.iter()
.map(|line| find_double(&line))
.map(|line| find_double(line))
.map_ok(priority)
.flatten_ok()
.fold_ok(0, |a, b| a + b)?;
Ok(ResultType::IntResult(sum))
Ok(ResultType::Integer(sum))
}
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
@ -30,7 +30,7 @@ impl DayTrait for Day {
.map_ok(priority)
.flatten_ok()
.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)?
}
fn find_badge<'a>(elves: &[&String]) -> Result<char, RucksackError> {
fn find_badge(elves: &[&String]) -> Result<char, RucksackError> {
if elves.len() < 2 {
return Err(RucksackError::NeedAtLeastTwo);
};
@ -109,7 +109,7 @@ mod test {
fn test_part1() -> Result<()> {
let day = Day {};
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)?;
assert_eq!(result, expected);
@ -120,7 +120,7 @@ mod test {
fn test_part2() -> Result<()> {
let day = Day {};
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)?;
assert_eq!(result, expected);

View file

@ -15,19 +15,19 @@ impl DayTrait for Day {
fn part1(&self, lines: &[String]) -> anyhow::Result<ResultType> {
let sum = lines
.iter()
.map(|line| parse(&line))
.map(|line| parse(line))
.filter_ok(fully_contained)
.fold_ok(0i64, |a, _| a + 1)?;
Ok(ResultType::IntResult(sum))
Ok(ResultType::Integer(sum))
}
fn part2(&self, lines: &[String]) -> anyhow::Result<ResultType> {
let sum = lines
.iter()
.map(|line| parse(&line))
.map(|line| parse(line))
.filter_ok(overlaps)
.fold_ok(0i64, |a, _| a + 1)?;
Ok(ResultType::IntResult(sum))
Ok(ResultType::Integer(sum))
}
}
@ -94,7 +94,7 @@ mod test {
fn test_part1() -> Result<()> {
let day = Day {};
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)?;
assert_eq!(result, expected);
@ -105,7 +105,7 @@ mod test {
fn test_part2() -> Result<()> {
let day = Day {};
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)?;
assert_eq!(result, expected);

View file

@ -3,10 +3,10 @@ use anyhow::Result;
#[allow(dead_code)]
#[derive(Debug, PartialEq, Eq)]
pub enum ResultType {
IntResult(i64),
StringResult(String),
LinesResult(Vec<String>),
NoResult,
Integer(i64),
String(String),
Lines(Vec<String>),
Nothing,
}
pub trait DayTrait {

View file

@ -11,9 +11,9 @@ use std::{
};
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 {
ResultType::IntResult(value) => {
ResultType::Integer(value) => {
println!(
"Day {:02} part {}: {} ({})",
day,
@ -22,7 +22,7 @@ fn output(day: usize, part: usize, result: ResultType, time: Duration) -> () {
time.as_secs_f64()
);
}
ResultType::StringResult(value) => {
ResultType::String(value) => {
println!(
"Day {:02} part {}: {} ({})",
day,
@ -31,7 +31,7 @@ fn output(day: usize, part: usize, result: ResultType, time: Duration) -> () {
time.as_secs_f32()
);
}
ResultType::LinesResult(value) => {
ResultType::Lines(value) => {
println!(
"Day {:02} part {}: {} ({})",
day,
@ -40,14 +40,14 @@ fn output(day: usize, part: usize, result: ResultType, time: Duration) -> () {
time.as_secs_f32()
);
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 result = if is_part1 {
day.part1(lines)?
@ -55,7 +55,7 @@ fn run_part(day: &Box<dyn DayTrait>, is_part1: bool, lines: &[String]) -> Result
day.part2(lines)?
};
if matches!(result, ResultType::NoResult) {
if matches!(result, ResultType::Nothing) {
Ok(Duration::ZERO)
} else {
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 elapsed1 = if part1 {
run_part(day, true, &lines)?
@ -99,25 +99,25 @@ fn run_on_parameters(params: &[String]) -> Result<()> {
0 => {
let mut runtime = Duration::ZERO;
for day in day_provider::get_all_days() {
runtime += run(&day, true, true)?;
runtime += run(day.as_ref(), true, true)?;
}
println!();
println!("Runtime: {}", runtime.as_secs_f32());
}
1 => {
let mut parts = params[0].split("/");
let mut parts = params[0].split('/');
if let Some(day_str) = parts.next() {
let day_number = day_str.parse::<usize>()?;
let day = day_provider::get_day(day_number)?;
if let Some(part_str) = parts.next() {
match part_str.parse::<usize>()? {
1 => run(&day, true, false)?,
2 => run(&day, false, true)?,
1 => run(day.as_ref(), true, false)?,
2 => run(day.as_ref(), false, true)?,
p => Err(ParamError::UnknownPart(p))?,
};
} else {
let runtime = run(&day, true, true)?;
let runtime = run(day.as_ref(), true, true)?;
println!("Runtime: {}", runtime.as_secs_f32());
}
}