applied clippy
This commit is contained in:
parent
33eb92e9d1
commit
4e08117ed0
16 changed files with 205 additions and 504 deletions
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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::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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
28
src/main.rs
28
src/main.rs
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue