diff --git a/Cargo.lock b/Cargo.lock index fb0624c..cf569c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,15 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "project_euler" version = "0.1.0" +dependencies = [ + "utils", +] + +[[package]] +name = "utils" +version = "0.1.0" +source = "git+https://git.plobos.xyz/projects/PuzzleUtils.git#d3a93a875f56c8f865411c0b7437986f413ca524" diff --git a/Cargo.toml b/Cargo.toml index dfe5f6c..caf82fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +utils = { git = "https://git.plobos.xyz/projects/PuzzleUtils.git" } diff --git a/src/bin/problem_12.rs b/src/bin/problem_12.rs index 709c60e..923113b 100644 --- a/src/bin/problem_12.rs +++ b/src/bin/problem_12.rs @@ -23,7 +23,7 @@ fn get_divisors(n: usize) -> Vec { divisors.push(potential_divisor); divisors.push(n / potential_divisor); } - potential_divisor = potential_divisor + 1; + potential_divisor += 1; } // This almost made me go mad if potential_divisor * potential_divisor == n { diff --git a/src/bin/problem_13.rs b/src/bin/problem_13.rs index 4709c97..579040a 100644 --- a/src/bin/problem_13.rs +++ b/src/bin/problem_13.rs @@ -1,4 +1,4 @@ -use project_euler::number::Number; +use utils::number::Number; fn main() { let mut sum = Number::from(0); diff --git a/src/bin/problem_15.rs b/src/bin/problem_15.rs index fd403aa..7dcc1f0 100644 --- a/src/bin/problem_15.rs +++ b/src/bin/problem_15.rs @@ -1,4 +1,4 @@ -use project_euler::number::Number; +use utils::number::Number; fn main() { let width = Number::from(20); diff --git a/src/bin/problem_16.rs b/src/bin/problem_16.rs index 80b28cd..9578cfc 100644 --- a/src/bin/problem_16.rs +++ b/src/bin/problem_16.rs @@ -1,4 +1,4 @@ -use project_euler::number::Number; +use utils::number::Number; fn main() { let power = get_power(1000); diff --git a/src/bin/problem_17.rs b/src/bin/problem_17.rs index 012ac4d..031b76a 100644 --- a/src/bin/problem_17.rs +++ b/src/bin/problem_17.rs @@ -1,4 +1,4 @@ -use project_euler::number::Number; +use utils::number::Number; fn main() { let mut num_letters = 0; diff --git a/src/bin/problem_2.rs b/src/bin/problem_2.rs index 47d1171..eb17bdb 100644 --- a/src/bin/problem_2.rs +++ b/src/bin/problem_2.rs @@ -14,7 +14,7 @@ fn fibonacci_even_sum(limit: i64) -> i64 { } } - return sum; + sum } #[cfg(test)] diff --git a/src/bin/problem_20.rs b/src/bin/problem_20.rs index 90de773..ab526b7 100644 --- a/src/bin/problem_20.rs +++ b/src/bin/problem_20.rs @@ -1,4 +1,4 @@ -use project_euler::number::Number; +use utils::number::Number; fn main() { let factorial = get_factorial(100); diff --git a/src/bin/problem_21.rs b/src/bin/problem_21.rs index 8c62888..2347fa5 100644 --- a/src/bin/problem_21.rs +++ b/src/bin/problem_21.rs @@ -9,10 +9,10 @@ fn main() { for i in 2..10000 { let divisors = get_divisors(i); let sum_divisors = divisors.iter().sum(); - if amicable_cache.get(&sum_divisors).is_some() { + if amicable_cache.contains_key(&sum_divisors) { continue; } - if despicable_cache.get(&sum_divisors).is_some() { + if despicable_cache.contains_key(&sum_divisors) { continue; } let other_divisors = get_divisors(sum_divisors); @@ -37,7 +37,7 @@ fn get_divisors(n: isize) -> Vec { divisors.insert(potential_divisor); divisors.insert(n / potential_divisor); } - potential_divisor = potential_divisor + 1; + potential_divisor += 1; } - divisors.iter().map(|&divisor| divisor).collect() + divisors.iter().copied().collect() } diff --git a/src/bin/problem_23.rs b/src/bin/problem_23.rs index 0d082c5..b71f186 100644 --- a/src/bin/problem_23.rs +++ b/src/bin/problem_23.rs @@ -14,12 +14,9 @@ fn main() { } let mut contained = false; for abundant in &abundants { - match abundants.binary_search(&(num - abundant)) { - Ok(_) => { - contained = true; - break; - } - Err(_) => {} + if abundants.binary_search(&(num - abundant)).is_ok() { + contained = true; + break; } } if !contained { @@ -54,7 +51,7 @@ fn get_divisors(n: usize) -> Vec { divisors.push(potential_divisor); divisors.push(n / potential_divisor); } - potential_divisor = potential_divisor + 1; + potential_divisor += 1; } // This almost made me go mad, should have used the one from 21 if potential_divisor * potential_divisor == n { diff --git a/src/bin/problem_24.rs b/src/bin/problem_24.rs index cdc14ac..25514cd 100644 --- a/src/bin/problem_24.rs +++ b/src/bin/problem_24.rs @@ -1,9 +1,9 @@ -use std::error::Error; +use utils::permutation::nth_lex; fn main() { let n = 1_000_000; let digits = vec![1, 0, 2, 3, 4, 5, 6, 7, 8, 9]; - let perm = permutation(digits, n) + let perm = nth_lex(digits, n) .expect("Should return ok") .iter() .map(|&digit| digit.to_string()) @@ -12,55 +12,14 @@ fn main() { println!("{perm}"); let digits = vec!["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; //for n in 1..=factorial(digits.len()) { - let perm = permutation(digits.clone(), n) + let perm = nth_lex(digits.clone(), n) .expect("Should return ok") .join(""); println!("{perm}"); //} let digits = vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]; - let perm = permutation(digits.clone(), n) + let perm = nth_lex(digits.clone(), n) .expect("Should return ok") .join(""); println!("{perm}"); } - -/// Explanation -/// -/// there are 10! possible permutations -/// for each first number there are 9!, for each first 2 numbers 8!, etc. -/// we check how many times we have 9! permutations before we're over 1_000_000 -/// aka. 1000000 / 9! -/// we take the remainder and check how many times we have 8! before we?re over it -/// (1000000 % 9!) 8! -/// etc. -/// every iteration we remove the digit by the idx from the original permutation -/// we only check for 999999 permutations because we already have the first one -/// -fn permutation(mut digits: Vec, nth: usize) -> Result, Box> { - digits.sort(); - if nth == 1 { - return Ok(digits); - } - if nth > factorial(digits.len()) || nth == 0 { - return Err(Box::from("Out of bounds")); - } - let mut perm = Vec::new(); - let num_unique_digits = digits.len(); - let mut remainder = nth - 1; - for idx in 1..=digits.len() { - let permutations = remainder / factorial(num_unique_digits - idx); - remainder = remainder % factorial(num_unique_digits - idx); - perm.push(digits[permutations]); - digits.remove(permutations); - } - Ok(perm) -} - -// number of permutations is n! where n is the number of digits -fn factorial(num: usize) -> usize { - let mut fact = 1; - for n in 1..=num { - fact = fact * n; - } - fact -} diff --git a/src/bin/problem_25.rs b/src/bin/problem_25.rs index 28b84dd..9bbf34e 100644 --- a/src/bin/problem_25.rs +++ b/src/bin/problem_25.rs @@ -1,67 +1,17 @@ -use project_euler::number::Number; +use utils::number::Number; fn main() { let fib_idx = find_fib(1000); println!("{fib_idx}"); } -// Way too slow, from 20 onward we go from µs to ms and from 32 we measure in seconds -//fn fib_recursion(n: Number) -> usize { -// let one = Number::from(1); -// if n == one { -// return 1; -// } -// let two = Number::from(2); -// if n == two { -// return 1; -// } -// fib_recursion(n.clone() - two) + fib_recursion(n - one) -//} - -// almost as fast as the no recursion solution but more complicated and more memory intensiv -// creating an inner function to not have to pass in the hashmap from outside makes it slightly slower -//fn fib_recursion_cached(n: Number) -> Number { -// let mut cache: HashMap = HashMap::new(); -// fn inner_fib_recursion_cached(n: Number, cache: &mut HashMap) -> Number { -// let one = Number::from(1); -// if n == one { -// return one; -// } -// let two = Number::from(2); -// if n == two { -// return one; -// } -// match cache.get(&n) { -// Some(res) => return res.clone(), -// None => { -// let res = inner_fib_recursion_cached(n.clone() - two, cache) + inner_fib_recursion_cached(n.clone() - one, cache); -// cache.insert(n.clone(), res.clone()); -// return res; -// }, -// } -// } -// inner_fib_recursion_cached(n, &mut cache) -//} - -// faster than recursion -fn fib(n: usize) -> Number { - let mut last_two = (Number::from(1), Number::from(1)); - let mut iteration = 1; - while iteration < n { - last_two = (last_two.1.clone(), last_two.0 + last_two.1); - iteration += 1; - } - - last_two.0 -} - fn find_fib(num_digits: usize) -> usize { let mut n = 1; loop { - let fib = fib(n); + let fib = Number::fib(n); let fib_len = fib.digits.len(); if fib_len == num_digits { - return n; + return n as usize; } n += 1; } diff --git a/src/bin/problem_28.rs b/src/bin/problem_28.rs index 6bd0b96..78e5439 100644 --- a/src/bin/problem_28.rs +++ b/src/bin/problem_28.rs @@ -13,7 +13,7 @@ fn main() { for corner in 0..4 { sum += last_square_end + (square * 2) * (corner + 1); } - last_square_end = last_square_end + (square * 2) * 4; + last_square_end += (square * 2) * 4; } println!("{sum}"); } diff --git a/src/bin/problem_29.rs b/src/bin/problem_29.rs index 354fbdc..9fce235 100644 --- a/src/bin/problem_29.rs +++ b/src/bin/problem_29.rs @@ -1,6 +1,7 @@ -use project_euler::number::Number; use std::collections::HashSet; +use utils::number::Number; + fn main() { let mut terms: HashSet = HashSet::new(); let max = 100; diff --git a/src/bin/problem_3.rs b/src/bin/problem_3.rs index 1a0859d..a3592ef 100644 --- a/src/bin/problem_3.rs +++ b/src/bin/problem_3.rs @@ -1,34 +1,6 @@ +use utils::math::prime_factors; + fn main() { let result = prime_factors(600851475143).into_iter().max(); println!("Result: {}", result.unwrap()); } - -fn prime_factors(number: i64) -> Vec { - let mut factors = vec![2]; - let upper: i64 = (number as f64).sqrt().ceil() as i64; - for i in 3..upper { - let mut is_prime = true; - for factor in &factors { - if i % factor == 0 { - is_prime = false; - break; - } - } - if is_prime && number % i == 0 { - factors.push(i); - } - } - - return factors; -} - -#[cfg(test)] -mod tests { - use crate::prime_factors; - - #[test] - fn it_works() { - let result = prime_factors(13195).into_iter().max(); - assert_eq!(result.unwrap(), 29); - } -} diff --git a/src/bin/problem_30.rs b/src/bin/problem_30.rs index 6d95907..6fa00f8 100644 --- a/src/bin/problem_30.rs +++ b/src/bin/problem_30.rs @@ -1,4 +1,4 @@ -use project_euler::number::Number; +use utils::number::Number; fn main() { println!("{}", nth_powers(5)) @@ -11,7 +11,7 @@ fn nth_powers(nth: u32) -> isize { loop { let attempt = max * idx; if Number::from(attempt).digits.len() < idx as usize { - max = (idx - 1) * max; + max *= idx - 1; break; } idx += 1; diff --git a/src/bin/problem_34.rs b/src/bin/problem_34.rs index 19898cf..48d3305 100644 --- a/src/bin/problem_34.rs +++ b/src/bin/problem_34.rs @@ -1,26 +1,18 @@ -use project_euler::number::Number; +use utils::{math::factorial, number::Number}; fn main() { let factorials_sum = digit_factorials(); println!("{factorials_sum}"); } -fn factorial(num: isize) -> isize { - let mut fact = 1; - for n in 1..=num { - fact = fact * n; - } - fact -} - fn digit_factorials() -> isize { let mut factorials = vec![]; - let mut max = factorial(9); + let mut max = factorial(9) as isize; let mut idx = 1; loop { let attempt = max * idx; if Number::from(attempt).digits.len() < idx as usize { - max = (idx - 1) * max; + max *= idx - 1; break; } idx += 1; @@ -29,7 +21,7 @@ fn digit_factorials() -> isize { let digits_fact_sum = Number::from(n) .digits .iter() - .map(|&digit| factorial(digit)) + .map(|&digit| factorial(digit as u64) as isize) .sum(); if n == digits_fact_sum { factorials.push(n); diff --git a/src/bin/problem_4.rs b/src/bin/problem_4.rs index c7c98e1..c86d560 100644 --- a/src/bin/problem_4.rs +++ b/src/bin/problem_4.rs @@ -16,7 +16,7 @@ fn find_largest_palindrome(digits: u32) -> i64 { } } - return largest; + largest } fn check_palindrome(number: i64) -> bool { @@ -27,7 +27,7 @@ fn check_palindrome(number: i64) -> bool { return false; } } - return true; + true } #[cfg(test)] diff --git a/src/bin/problem_48.rs b/src/bin/problem_48.rs index fcfdd52..a3c4e3d 100644 --- a/src/bin/problem_48.rs +++ b/src/bin/problem_48.rs @@ -1,4 +1,4 @@ -use project_euler::number::Number; +use utils::number::Number; fn main() { println!("{}", power_series(1000)); diff --git a/src/bin/problem_50.rs b/src/bin/problem_50.rs index 46dc38d..c1a307d 100644 --- a/src/bin/problem_50.rs +++ b/src/bin/problem_50.rs @@ -24,7 +24,7 @@ fn solve() -> usize { let mut chain_length = primes.len() - 1; loop { for prime_window in primes.windows(chain_length) { - let sum = prime_window.iter().map(|&prime| prime).sum::(); + let sum = prime_window.iter().copied().sum::(); if primes.contains(&sum) { return sum; } diff --git a/src/bin/problem_6.rs b/src/bin/problem_6.rs index d5c1376..40e7968 100644 --- a/src/bin/problem_6.rs +++ b/src/bin/problem_6.rs @@ -1,17 +1,19 @@ +use utils::math::factorial; + fn main() { let result = smallest_multiple(20); println!("Result: {result}"); } fn smallest_multiple(number: i64) -> i64 { - let factorial = factorial(number); + let factorial = factorial(number.try_into().unwrap()) as i64; for i in number..=factorial { if is_multiple(i, number) { return i; } } - return factorial; + factorial } fn is_multiple(number: i64, range: i64) -> bool { @@ -23,14 +25,6 @@ fn is_multiple(number: i64, range: i64) -> bool { true } -fn factorial(n: i64) -> i64 { - let mut result = 1; - for i in 1..=n { - result *= i; - } - return result; -} - #[cfg(test)] mod tests { use crate::smallest_multiple; diff --git a/src/bin/problem_7.rs b/src/bin/problem_7.rs index fda6206..01823f4 100644 --- a/src/bin/problem_7.rs +++ b/src/bin/problem_7.rs @@ -1,30 +1,10 @@ +use utils::math::nth_prime; + fn main() { let result = nth_prime(10001); println!("Result: {}", result.unwrap()); } -fn nth_prime(nth: i64) -> Option { - let mut primes: Vec = vec![2]; - - let mut i = 3; - - while primes.len() < nth as usize { - let mut is_prime = true; - for prime in &primes { - if i % prime == 0 { - is_prime = false; - break; - } - } - if is_prime { - primes.push(i); - } - i += 1; - } - - return primes.pop(); -} - #[cfg(test)] mod tests { use crate::nth_prime; diff --git a/src/bin/problem_8.rs b/src/bin/problem_8.rs index 9f0e519..44e81e9 100644 --- a/src/bin/problem_8.rs +++ b/src/bin/problem_8.rs @@ -19,7 +19,7 @@ fn adjacent_product(number: &str, window: usize) -> i64 { .max() .unwrap(); - return result; + result } #[cfg(test)] diff --git a/src/bin/problem_9.rs b/src/bin/problem_9.rs index 67ae407..cf7b307 100644 --- a/src/bin/problem_9.rs +++ b/src/bin/problem_9.rs @@ -14,5 +14,5 @@ fn main() { } fn is_triplet(a: usize, b: usize, c: usize) -> bool { - return a * a + b * b == c * c; + a * a + b * b == c * c } diff --git a/src/lib.rs b/src/lib.rs deleted file mode 100644 index 67eb8f6..0000000 --- a/src/lib.rs +++ /dev/null @@ -1,414 +0,0 @@ -pub mod number { - use std::cmp::{min, Ordering}; - use std::fmt::{Display, Formatter}; - use std::iter::zip; - use std::ops::{Add, Div, Mul, Rem, Sub}; - - #[derive(Clone, Debug, Eq, PartialEq, Hash)] - pub enum Sign { - Positif, - Negatif, - } - - #[derive(Clone, Debug, Eq, PartialEq, Hash)] - pub struct Number { - pub digits: Vec, - pub sign: Sign, - } - - impl Number { - pub fn get_digit(n: isize, pos: usize) -> isize { - let modulo = 10isize.pow(pos as u32 + 1); - let divisor = modulo / 10; - (n % modulo) / divisor - } - - pub const fn byte_to_digit(b: u8) -> isize { - // wrapping_sub('0' as u32) same as - 48 but less magical - (b as isize).wrapping_sub('0' as isize) - } - - pub fn handle_overflows(&mut self) { - let new_digits = &mut self.digits; - let digits_len = new_digits.len(); - let mut digits_idx = digits_len - 1; - loop { - let digit_or_num = new_digits[digits_idx]; - let digit_len = if digit_or_num != 0 { - (digit_or_num.abs() as f64 + 1.0).log10().ceil() as usize - } else { - 1 - }; - for i in 0..digit_len { - let new_digit = Self::get_digit(digit_or_num, i); - let (digit_idx, is_overflow) = digits_idx.overflowing_sub(i); - if is_overflow { - new_digits.insert(0, new_digit); - digits_idx += 1; - } else { - let digit = new_digits.get_mut(digit_idx).unwrap(); - if i == 0 { - *digit = new_digit; - } else { - *digit += new_digit; - } - } - } - if digits_idx == 0 { - break; - } - digits_idx -= 1; - } - } - - pub fn handle_underflows(&mut self) { - let new_digits = &mut self.digits; - let mut digits_len = new_digits.len(); - for digit in new_digits.clone() { - match digit.cmp(&0) { - Ordering::Equal => { - if digits_len == 1 { - return; - } - digits_len -= 1; - new_digits.remove(0); - } - Ordering::Less => { - self.sign = Sign::Negatif; - break; - } - _ => break, - }; - } - let mut digits_idx = digits_len - 1; - loop { - let digit = new_digits[digits_idx]; - if self.sign == Sign::Positif && digit < 0 && digits_idx > 0 { - let mut_digit = new_digits.get_mut(digits_idx).unwrap(); - *mut_digit = 10 - digit.abs(); - let mut_digit = new_digits.get_mut(digits_idx - 1).unwrap(); - *mut_digit -= 1; - } else { - let mut_digit = new_digits.get_mut(digits_idx).unwrap(); - *mut_digit = digit.abs(); - } - if digits_idx == 0 { - break; - } - digits_idx -= 1; - } - for digit in new_digits.clone() { - match digit.cmp(&0) { - Ordering::Equal => { - new_digits.remove(0); - } - _ => break, - }; - } - } - - 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); - for _i in 1..n { - result = result * number; - } - result - } else { - let number = self.clone(); - for _i in 1..n { - result = result * number.clone(); - } - result - } - } - - 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); - for n in 1..=max { - fact = fact * n; - } - fact - } else { - panic!("starting number too big") - } - } - - fn div_with_rem(n1: Number, n2: Number) -> (Number, Number) { - let n1_len = n1.digits.len(); - let n2_len = n2.digits.len(); - if n2_len > n1_len { - return (Number::from(0), n2); - } - let dividend = n1.digits[..n2_len].to_vec(); - let mut quotient = vec![]; - let mut remainder = Number { - digits: dividend.clone(), - sign: Sign::Positif, - }; - let mut iteration = 1; - loop { - let mut factor = 0; - loop { - let temp_remainder = remainder.clone() - n2.clone(); - if temp_remainder.sign == Sign::Negatif { - quotient.push(factor); - break; - } - remainder = temp_remainder; - factor += 1; - } - if n1_len == n2_len + iteration - 1 { - break; - } - remainder.digits.push(n1.digits[n2_len + iteration - 1]); - iteration += 1; - } - let mut res = Number { - digits: quotient, - sign: Sign::Positif, - }; - res.handle_overflows(); - for digit in res.clone().digits { - if digit != 0 { - break; - } - res.digits.remove(0); - } - for digit in remainder.clone().digits { - if digit != 0 || remainder.digits.len() == 1 { - break; - } - remainder.digits.remove(0); - } - (res, remainder) - } - } - - impl From for isize { - fn from(value: Number) -> Self { - let mut num = 0; - for (pos, &digit) in value.digits.iter().rev().enumerate() { - num += digit * 10isize.pow(pos as u32); - } - num - } - } - - impl From for String { - fn from(value: Number) -> Self { - let string_vec: Vec = value - .digits - .iter() - .map(|&digit| digit.to_string()) - .collect(); - string_vec.concat() - } - } - - impl From<&str> for Number { - fn from(value: &str) -> Self { - let bytes = value.as_bytes(); - let (sign, idx_start) = match bytes[0] { - b'-' => (Sign::Negatif, 1), - _ => (Sign::Positif, 0), - }; - let mut digits = vec![]; - for &byte in &bytes[idx_start..] { - let digit = Self::byte_to_digit(byte); - digits.push(digit); - } - Self { digits, sign } - } - } - - impl From for Number { - fn from(value: isize) -> Self { - let mut sign = Sign::Positif; - if value < 0 { - sign = Sign::Negatif; - } - let num_len = if value > 0 { - (value as f64 + 1.0).log10().ceil() as usize - } else { - 1 - }; - let mut digits = vec![]; - for digit_idx in 0..num_len { - let digit = Self::get_digit(value, digit_idx); - digits.push(digit); - } - let digits = digits.iter().rev().copied().collect(); - Self { digits, sign } - } - } - - impl Display for Number { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let number_string = self - .digits - .iter() - .map(|&digit| digit.to_string()) - .collect::>() - .join(""); - match self.sign { - Sign::Positif => write!(f, "{number_string}"), - Sign::Negatif => write!(f, "-{number_string}"), - } - } - } - - impl Add for Number { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - let self_len = self.digits.len(); - let rhs_len = rhs.digits.len(); - let mut self_digits = self.digits.clone(); - let mut rhs_digits = rhs.digits.clone(); - if self_len != rhs_len { - let difference = (self_len).abs_diff(rhs_len); - let pad = vec![0isize; difference]; - if min(self_len, rhs_len) == self_len { - self_digits = [pad, self.digits].concat(); - } else { - rhs_digits = [pad, rhs.digits].concat(); - } - } - let zipped = zip(self_digits.iter(), rhs_digits.iter()); - let added = zipped - .map(|(self_digit, rhs_digit)| self_digit + rhs_digit) - .collect(); - let mut overflown_number = Self { - digits: added, - sign: Sign::Positif, - }; - overflown_number.handle_overflows(); - overflown_number - } - } - - impl Sub for Number { - type Output = Self; - - fn sub(self, rhs: Self) -> Self::Output { - let self_len = self.digits.len(); - let rhs_len = rhs.digits.len(); - let mut self_digits = self.digits.clone(); - let mut rhs_digits = rhs.digits.clone(); - if self_len != rhs_len { - let difference = (self_len).abs_diff(rhs_len); - let pad = vec![0isize; difference]; - if min(self_len, rhs_len) == self_len { - self_digits = [pad, self.digits].concat(); - } else { - rhs_digits = [pad, rhs.digits].concat(); - } - } - let zipped = zip(self_digits.iter(), rhs_digits.iter()); - let added = zipped - .map(|(self_digit, rhs_digit)| self_digit - rhs_digit) - .collect(); - let mut underflown_number = Self { - digits: added, - sign: Sign::Positif, - }; - underflown_number.handle_underflows(); - underflown_number - } - } - - impl Mul for Number { - type Output = Self; - - fn mul(self, rhs: Self) -> Self::Output { - let multiplied = self.digits.iter().rev().enumerate().map(|(pos, &digit)| { - let mut mult = digit * rhs.clone(); - mult.digits = [mult.digits, vec![0; pos]].concat(); - mult - }); - let mut overflown_number = multiplied.reduce(|acc, num| acc + num).unwrap(); - overflown_number.handle_overflows(); - overflown_number - } - } - - impl Mul for isize { - type Output = Number; - - fn mul(self, rhs: Number) -> Self::Output { - let multiplied = rhs.digits.iter().map(|digit| digit * self).collect(); - let mut overflown_number = Number { - digits: multiplied, - sign: Sign::Positif, - }; - overflown_number.handle_overflows(); - overflown_number - } - } - - impl Mul for Number { - type Output = Self; - - fn mul(self, rhs: isize) -> Self::Output { - let multiplied = self.digits.iter().map(|digit| digit * rhs).collect(); - let mut overflown_number = Self { - digits: multiplied, - sign: Sign::Positif, - }; - overflown_number.handle_overflows(); - overflown_number - } - } - - impl Div for Number { - type Output = Self; - - fn div(self, rhs: Self) -> Self::Output { - Self::div_with_rem(self, rhs).0 - } - } - - impl Rem for Number { - type Output = Self; - - fn rem(self, rhs: Self) -> Self::Output { - Self::div_with_rem(self, rhs).1 - } - } - - #[cfg(test)] - mod number_tests { - use crate::number::{Number, Sign}; - - #[test] - fn test_from_isize() { - let number = Number::from(-1234); - assert_eq!( - number, - Number { - digits: vec![1234], - sign: Sign::Negatif - } - ); - } - - #[test] - fn test_get_digit() { - let num = 12345; - let digit_1 = Number::get_digit(num, 0); - let digit_2 = Number::get_digit(num, 1); - let digit_3 = Number::get_digit(num, 2); - let digit_4 = Number::get_digit(num, 3); - let digit_5 = Number::get_digit(num, 4); - assert_eq!(digit_1, 5); - assert_eq!(digit_2, 4); - assert_eq!(digit_3, 3); - assert_eq!(digit_4, 2); - assert_eq!(digit_5, 1); - } - } -}