diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..ce8530f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "utils" +version = "0.1.0" diff --git a/src/combination.rs b/src/combination.rs new file mode 100644 index 0000000..4bd05e6 --- /dev/null +++ b/src/combination.rs @@ -0,0 +1,104 @@ +use std::error::Error; + +fn factorial(num: usize) -> usize { + let mut fact = 1; + for n in 1..=num { + fact *= n; + } + fact +} + +fn binomial(n: usize, k: usize) -> usize { + if k > n { + 0 + } else { + factorial(n) / (factorial(k) * factorial(n - k)) + } +} + +#[derive(Clone)] +pub struct Combinator { + pub current: Vec, + pub k: usize, + idx: usize, +} + +impl Combinator { + pub fn new(elements: Vec, k: usize) -> Result, Box> { + if k > elements.len() || k == 0 { + return Err(Box::from("Out of bounds")); + } + Ok(Self { + current: elements, + k, + idx: 0, + }) + } + + pub fn nth_lex(mut elements: Vec, k: usize, nth: usize) -> Result, Box> { + elements.sort(); + let num_elements = elements.len(); + let num_combinations = binomial(num_elements, k); + if nth > num_combinations || k > num_elements || nth == 0 || k == 0 { + return Err(Box::from("Out of bounds")); + } + let mut i = 0; + let mut remaining_k = k; + let mut comb = Vec::new(); + let mut remainder = nth - 1; + while remaining_k > 0 { + // Count the number of combinations that start with elements[i] + // example with n = 5, k = 2 + // nth <= 4 select first + // nth <= 7 select second + // nth <= 9 select third + // nth == 10 select fourth + let count = binomial(num_elements - i - 1, remaining_k - 1); + if remainder < count { + // If the nth combination is within the count, pick this element + comb.push(elements[i].clone()); + remaining_k -= 1; + } else { + remainder -= count; + } + i += 1; + } + Ok(comb) + } +} + +impl Iterator for Combinator { + type Item = Vec; + + fn next(&mut self) -> Option { + let num_elements = self.current.len(); + let num_combinations = binomial(num_elements, self.k); + if self.idx == num_combinations { + return None; + } + let mut i = 0; + let mut remaining_k = self.k; + let mut comb = Vec::new(); + let mut remainder = self.idx - 1; + while remaining_k > 0 { + // Count the number of combinations that start with elements[i] + // example with n = 5, k = 2 + // nth <= 4 select first + // nth <= 7 select second + // nth <= 9 select third + // nth == 10 select fourth + let count = binomial(num_elements - i - 1, remaining_k - 1); + if remainder < count { + // If the nth combination is within the count, pick this element + comb.push(self.current[i].clone()); + remaining_k -= 1; + } else { + remainder -= count; + } + i += 1; + } + self.idx += 1; + self.current = comb; + Some(self.current.clone()) + } +} diff --git a/src/grid.rs b/src/grid.rs new file mode 100644 index 0000000..ff76b51 --- /dev/null +++ b/src/grid.rs @@ -0,0 +1,33 @@ +use std::error::Error; + +#[derive(Debug)] +pub struct Grid(pub Vec>); + +impl Grid { + pub fn new(grid: Vec>) -> Result> { + let row_length = grid[0].len(); + for row in &grid { + if row_length != row.len() { + return Err(Box::from("Rows need to all be equal in length")); + } + } + Ok(Grid(grid)) + } + + pub fn invert(&mut self) -> Self { + let height = self.0.len(); + let width = self.0[0].len(); + + let mut new_grid = Vec::with_capacity(width); + + for col_idx in 0..width { + let mut new_row = Vec::with_capacity(height); + for row_idx in 0..height { + new_row.push(self.0[row_idx][col_idx].clone()); + } + new_grid.push(new_row); + } + self.0 = new_grid; + Grid(self.0.clone()) + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..40ccb35 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,5 @@ +pub mod combination; +pub mod grid; +pub mod math; +pub mod number; +pub mod permutation; diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/src/math.rs b/src/math.rs new file mode 100644 index 0000000..1a0fb80 --- /dev/null +++ b/src/math.rs @@ -0,0 +1,74 @@ +use std::collections::HashSet; + +pub fn prime_factors(number: u64) -> Vec { + let mut factors = vec![2]; + let upper: u64 = (number as f64).sqrt().ceil() as u64; + 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); + } + } + + factors +} + +pub 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; + } + + primes.pop() +} + +pub fn factorial(n: u64) -> u64 { + let mut result = 1; + for i in 1..=n { + result *= i; + } + result +} + +pub fn get_divisors(n: u64) -> Vec { + let mut divisors = HashSet::from([1]); + let mut potential_divisor = 2; + while (potential_divisor * potential_divisor) <= n { + if n % potential_divisor == 0 { + divisors.insert(potential_divisor); + divisors.insert(n / potential_divisor); + } + potential_divisor += 1; + } + divisors.iter().copied().collect() +} + +pub fn fib(n: u64) -> u64 { + let mut last_two = (1, 1); + let mut iteration = 1; + while iteration < n { + last_two = (last_two.1, last_two.0 + last_two.1); + iteration += 1; + } + + last_two.0 +} diff --git a/src/number.rs b/src/number.rs new file mode 100644 index 0000000..cf4ecfc --- /dev/null +++ b/src/number.rs @@ -0,0 +1,423 @@ +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) + } + + 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; + } + } + + 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") + } + } + + pub fn fib(n: u64) -> Self { + let mut last_two = (Self::from(1), Self::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 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); + } +} diff --git a/src/permutation.rs b/src/permutation.rs new file mode 100644 index 0000000..98e911d --- /dev/null +++ b/src/permutation.rs @@ -0,0 +1,83 @@ +use std::error::Error; + +fn factorial(num: usize) -> usize { + let mut fact = 1; + for n in 1..=num { + fact *= n; + } + fact +} + +#[derive(Clone)] +pub struct Permutator { + pub current: Vec, + idx: usize, +} + +impl Permutator { + pub fn new(elements: Vec) -> Self { + Self { + current: elements, + idx: 0, + } + } + + /// 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 + /// + pub fn nth_lex(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 %= factorial(num_unique_digits - idx); + perm.push(digits[permutations]); + digits.remove(permutations); + } + Ok(perm) + } +} + +impl Iterator for Permutator { + type Item = Vec; + /// Returns the next permutation and changes the current permutation to it + /// This operation wraps around + fn next(&mut self) -> Option { + if self.current.is_empty() { + return None; + } + let mut digits = self.current.clone(); + if self.idx == factorial(digits.len()) { + return None; + } + let mut perm = Vec::new(); + let num_unique_digits = digits.len(); + let mut remainder = 1; + for idx in 1..=digits.len() { + let permutations = remainder / factorial(num_unique_digits - idx); + remainder %= factorial(num_unique_digits - idx); + perm.push(digits[permutations]); + digits.remove(permutations); + } + self.idx += 1; + self.current = digits; + Some(self.current.clone()) + } +}