From b44908429ac267730665ffc861b7b897445b5d95 Mon Sep 17 00:00:00 2001 From: Fabian Schmidt Date: Wed, 20 Nov 2024 12:34:05 +0100 Subject: [PATCH] Remove get_recurring from fraction as it is not really useful I think other than for euler 26 --- src/fraction.rs | 37 +-------------- src/number.rs | 119 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 114 insertions(+), 42 deletions(-) diff --git a/src/fraction.rs b/src/fraction.rs index 5da449a..a5fc803 100644 --- a/src/fraction.rs +++ b/src/fraction.rs @@ -1,4 +1,4 @@ -use std::{collections::HashSet, error::Error}; +use std::error::Error; use crate::number::Number; @@ -31,38 +31,10 @@ impl Fraction { self.numerator = self.numerator.clone() / gcd.clone(); self.denominator = self.denominator.clone() / gcd.clone(); } - - pub fn get_repeating(&self) -> Number { - let mut memory = HashSet::new(); - let mut div_with = self.numerator.clone(); - let mut repetition = Vec::new(); - let num_len = self.numerator.digits.len(); - for _ in 0..num_len { - div_with = div_with * 10; - } - loop { - println!("{div_with}/{}", self.denominator.clone()); - let (div, rem) = - Number::div_with_rem(div_with.clone(), self.denominator.clone()).unwrap(); - println!("div: {div}, rem: {rem}"); - if div == 0.into() || rem == 0.into() || memory.contains(&rem) { - repetition.push(div.digits[0]); - return Number { - digits: repetition, - sign: crate::number::Sign::Positif, - }; - } - memory.insert(rem.clone()); - repetition.push(div.digits[0]); - div_with = rem * 10; - } - } } #[cfg(test)] mod test { - use crate::number::Number; - use super::Fraction; #[test] @@ -76,11 +48,4 @@ mod test { } ); } - - #[test] - fn test_repeating() { - let f = Fraction::new(1.into(), 7.into()).unwrap(); - let rep = f.get_repeating(); - assert_eq!(rep, Number::from("142857")); - } } diff --git a/src/number.rs b/src/number.rs index 8f01a4e..8591b0a 100644 --- a/src/number.rs +++ b/src/number.rs @@ -110,7 +110,7 @@ impl Number { pub fn pow(self, n: u32) -> Self { let mut result = self.clone(); if ((self.digits.len() * 8) as u32) < isize::BITS { - let number = isize::from(self); + let number = isize::try_from(self).unwrap(); for _i in 1..n { result = result * number; } @@ -127,7 +127,7 @@ impl Number { pub fn fact(self) -> Self { let mut fact = Number::from(1); if ((self.digits.len() * 8) as u32) < isize::BITS { - let max = isize::from(self); + let max = isize::try_from(self).unwrap(); for n in 1..=max { fact = fact * n; } @@ -213,13 +213,19 @@ impl Number { } } -impl From for isize { - fn from(value: Number) -> Self { +impl TryFrom for isize { + type Error = Box; + + fn try_from(value: Number) -> Result { let mut num = 0; for (pos, &digit) in value.digits.iter().rev().enumerate() { - num += digit * 10isize.pow(pos as u32); + let mul = digit.checked_mul(10isize.pow(pos as u32)); + if mul.is_none() { + return Err(Box::from("Cannot convert Number to isize. Too big.")); + } + num += mul.unwrap(); } - num + Ok(num) } } @@ -408,6 +414,51 @@ impl Rem for Number { } } +impl PartialOrd for Number { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Number { + fn cmp(&self, other: &Self) -> Ordering { + if self.sign == Sign::Negatif && other.sign == Sign::Positif { + return Ordering::Less; + } else if self.sign == Sign::Positif && other.sign == Sign::Negatif { + return Ordering::Greater; + } + if self.digits.len() < other.digits.len() { + if self.sign == Sign::Positif { + return Ordering::Less; + } else if self.sign == Sign::Negatif { + return Ordering::Greater; + } + } else if self.digits.len() > other.digits.len() { + if self.sign == Sign::Positif { + return Ordering::Greater; + } else if self.sign == Sign::Negatif { + return Ordering::Less; + } + } + for pair in zip(&self.digits, &other.digits) { + if pair.0 < pair.1 { + if self.sign == Sign::Positif { + return Ordering::Less; + } else if self.sign == Sign::Negatif { + return Ordering::Greater; + } + } else if pair.0 > pair.1 { + if self.sign == Sign::Positif { + return Ordering::Greater; + } else if self.sign == Sign::Negatif { + return Ordering::Less; + } + } + } + Ordering::Equal + } +} + #[cfg(test)] mod number_tests { use crate::number::{Number, Sign}; @@ -450,4 +501,60 @@ mod number_tests { assert_eq!(digit_4, 2); assert_eq!(digit_5, 1); } + + #[test] + fn test_cmp_eq_pos() { + let a = Number::from(1); + let b = Number::from(1); + assert_eq!(a, b); + } + + #[test] + fn test_cmp_eq_neg() { + let a = Number::from(-1); + let b = Number::from(-1); + assert_eq!(a, b); + } + + #[test] + fn test_cmp_pos_neg() { + let a = Number::from(1); + let b = Number::from(-1); + assert!(a > b); + } + + #[test] + fn test_cmp_neg_pos() { + let a = Number::from(-1); + let b = Number::from(1); + assert!(a < b); + } + + #[test] + fn test_cmp_short_neg() { + let a = Number::from(-1); + let b = Number::from(-10); + assert!(a > b); + } + + #[test] + fn test_cmp_short_pos() { + let a = Number::from(1); + let b = Number::from(10); + assert!(a < b); + } + + #[test] + fn test_cmp_long_neg() { + let a = Number::from(-10); + let b = Number::from(-1); + assert!(a < b); + } + + #[test] + fn test_cmp_long_pos() { + let a = Number::from(10); + let b = Number::from(1); + assert!(a > b); + } }