Compare commits
	
		
			12 Commits
		
	
	
		
			23a96d5bee
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8e297a3e84 | |||
| bfbdb6a20e | |||
| 87b4b49dad | |||
| e293fb90d3 | |||
| cc626a6d85 | |||
| 19b2434789 | |||
| 9f10cee3e0 | |||
| 1e0f6fd077 | |||
| cad2d2b910 | |||
| 50b2aa8932 | |||
| ed886762d0 | |||
| 2ec7e6c296 | 
| @@ -53,7 +53,7 @@ pub fn nth_lex<T: Clone + Ord>( | |||||||
|  |  | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct Combinator<T: Clone + Ord> { | pub struct Combinator<T: Clone + Ord> { | ||||||
|     pub current: Vec<T>, |     pub elements: Vec<T>, | ||||||
|     pub k: usize, |     pub k: usize, | ||||||
|     idx: usize, |     idx: usize, | ||||||
| } | } | ||||||
| @@ -64,7 +64,7 @@ impl<T: Clone + Ord> Combinator<T> { | |||||||
|             return Err(Box::from("Out of bounds")); |             return Err(Box::from("Out of bounds")); | ||||||
|         } |         } | ||||||
|         Ok(Self { |         Ok(Self { | ||||||
|             current: elements, |             elements, | ||||||
|             k, |             k, | ||||||
|             idx: 0, |             idx: 0, | ||||||
|         }) |         }) | ||||||
| @@ -75,7 +75,7 @@ impl<T: Clone + Ord> Iterator for Combinator<T> { | |||||||
|     type Item = Vec<T>; |     type Item = Vec<T>; | ||||||
|  |  | ||||||
|     fn next(&mut self) -> Option<Self::Item> { |     fn next(&mut self) -> Option<Self::Item> { | ||||||
|         let num_elements = self.current.len(); |         let num_elements = self.elements.len(); | ||||||
|         let num_combinations = binomial(num_elements, self.k); |         let num_combinations = binomial(num_elements, self.k); | ||||||
|         if self.idx == num_combinations { |         if self.idx == num_combinations { | ||||||
|             return None; |             return None; | ||||||
| @@ -83,7 +83,7 @@ impl<T: Clone + Ord> Iterator for Combinator<T> { | |||||||
|         let mut i = 0; |         let mut i = 0; | ||||||
|         let mut remaining_k = self.k; |         let mut remaining_k = self.k; | ||||||
|         let mut comb = Vec::new(); |         let mut comb = Vec::new(); | ||||||
|         let mut remainder = self.idx - 1; |         let mut remainder = self.idx; | ||||||
|         while remaining_k > 0 { |         while remaining_k > 0 { | ||||||
|             // Count the number of combinations that start with elements[i] |             // Count the number of combinations that start with elements[i] | ||||||
|             // example with n = 5, k = 2 |             // example with n = 5, k = 2 | ||||||
| @@ -94,7 +94,7 @@ impl<T: Clone + Ord> Iterator for Combinator<T> { | |||||||
|             let count = binomial(num_elements - i - 1, remaining_k - 1); |             let count = binomial(num_elements - i - 1, remaining_k - 1); | ||||||
|             if remainder < count { |             if remainder < count { | ||||||
|                 // If the nth combination is within the count, pick this element |                 // If the nth combination is within the count, pick this element | ||||||
|                 comb.push(self.current[i].clone()); |                 comb.push(self.elements[i].clone()); | ||||||
|                 remaining_k -= 1; |                 remaining_k -= 1; | ||||||
|             } else { |             } else { | ||||||
|                 remainder -= count; |                 remainder -= count; | ||||||
| @@ -102,7 +102,143 @@ impl<T: Clone + Ord> Iterator for Combinator<T> { | |||||||
|             i += 1; |             i += 1; | ||||||
|         } |         } | ||||||
|         self.idx += 1; |         self.idx += 1; | ||||||
|         self.current = comb; |         Some(comb) | ||||||
|         Some(self.current.clone()) |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod test { | ||||||
|  |     use crate::combination::{nth_lex, Combinator}; | ||||||
|  |  | ||||||
|  |     const SMALL: [i8; 5] = [1, 2, 3, 4, 5]; | ||||||
|  |  | ||||||
|  |     // Nth Lex | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn nth_lex_zero_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         assert!(nth_lex(small, 0, 1).is_err()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn nth_lex_more_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         assert!(nth_lex(small, 6, 1).is_err()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn nth_lex_all_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         assert!(nth_lex(small.clone(), 5, 1).unwrap() == vec![1, 2, 3, 4, 5]); | ||||||
|  |         assert!(nth_lex(small, 5, 2).is_err()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn nth_lex_some_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2, 1).unwrap(), vec![1, 2]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2, 2).unwrap(), vec![1, 3]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2, 3).unwrap(), vec![1, 4]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2, 4).unwrap(), vec![1, 5]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2, 5).unwrap(), vec![2, 3]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2, 6).unwrap(), vec![2, 4]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2, 7).unwrap(), vec![2, 5]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2, 8).unwrap(), vec![3, 4]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2, 9).unwrap(), vec![3, 5]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2, 10).unwrap(), vec![4, 5]); | ||||||
|  |         assert!(nth_lex(small, 2, 11).is_err()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn nth_lex_one_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 1, 1).unwrap(), vec![1]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 1, 2).unwrap(), vec![2]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 1, 3).unwrap(), vec![3]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 1, 4).unwrap(), vec![4]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 1, 5).unwrap(), vec![5]); | ||||||
|  |         assert!(nth_lex(small, 1, 6).is_err()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Can't yet use too big values | ||||||
|  |     //#[test] | ||||||
|  |     //fn nth_lex_all_big() { | ||||||
|  |     //    let big: Vec<i32> = (0..100).collect(); | ||||||
|  |     //    assert_eq!( | ||||||
|  |     //        nth_lex(big.clone(), 100, 1).unwrap(), | ||||||
|  |     //        (0..100).collect::<Vec<i32>>() | ||||||
|  |     //    ); | ||||||
|  |     //    assert!(nth_lex(big, 100, 2).is_err()); | ||||||
|  |     //} | ||||||
|  |  | ||||||
|  |     //#[test] | ||||||
|  |     //fn nth_lex_some_big() { | ||||||
|  |     //    let big: Vec<i32> = (0..100).collect(); | ||||||
|  |     //    assert_eq!( | ||||||
|  |     //        nth_lex(big.clone(), 50, 1).unwrap(), | ||||||
|  |     //        (0..50).collect::<Vec<i32>>() | ||||||
|  |     //    ); | ||||||
|  |     //} | ||||||
|  |  | ||||||
|  |     //#[test] | ||||||
|  |     //fn nth_lex_one_big() { | ||||||
|  |     //    let big: Vec<i32> = (0..100).collect(); | ||||||
|  |     //    assert_eq!(nth_lex(big.clone(), 1, 1).unwrap(), vec![0]); | ||||||
|  |     //    assert_eq!(nth_lex(big.clone(), 1, 2).unwrap(), vec![1]); | ||||||
|  |     //    assert_eq!(nth_lex(big.clone(), 1, 3).unwrap(), vec![2]); | ||||||
|  |     //    assert_eq!(nth_lex(big.clone(), 1, 4).unwrap(), vec![3]); | ||||||
|  |     //} | ||||||
|  |  | ||||||
|  |     // Combinator | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn comb_zero_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         let comb = Combinator::new(small, 0); | ||||||
|  |         assert!(comb.is_err()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn comb_more_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         let comb = Combinator::new(small, 6); | ||||||
|  |         assert!(comb.is_err()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn comb_all_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         let mut comb = Combinator::new(small, 5).unwrap(); | ||||||
|  |         assert!(comb.next() == Some(vec![1, 2, 3, 4, 5])); | ||||||
|  |         assert!(comb.next().is_none()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn comb_some_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         let mut comb = Combinator::new(small, 2).unwrap(); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![1, 2])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![1, 3])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![1, 4])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![1, 5])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![2, 3])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![2, 4])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![2, 5])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![3, 4])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![3, 5])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![4, 5])); | ||||||
|  |         assert!(comb.next().is_none()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn comb_one_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         let mut comb = Combinator::new(small, 1).unwrap(); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![1])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![2])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![3])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![4])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![5])); | ||||||
|  |         assert!(comb.next().is_none()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ pub struct Rational { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl Fraction { | impl Fraction { | ||||||
|     pub fn new(numerator: Number, denominator: Number) -> Result<Self, Box<dyn Error>> { |     pub fn new(mut numerator: Number, mut denominator: Number) -> Result<Self, Box<dyn Error>> { | ||||||
|         if denominator == 0.into() { |         if denominator == 0.into() { | ||||||
|             return Err(Box::from("Division by 0")); |             return Err(Box::from("Division by 0")); | ||||||
|         } |         } | ||||||
| @@ -33,6 +33,8 @@ impl Fraction { | |||||||
|                 Sign::Negatif => Sign::Positif, |                 Sign::Negatif => Sign::Positif, | ||||||
|             }, |             }, | ||||||
|         }; |         }; | ||||||
|  |         numerator.sign = Sign::Positif; | ||||||
|  |         denominator.sign = Sign::Positif; | ||||||
|         let mut f = Fraction { |         let mut f = Fraction { | ||||||
|             numerator, |             numerator, | ||||||
|             denominator, |             denominator, | ||||||
|   | |||||||
							
								
								
									
										244
									
								
								src/grid.rs
									
									
									
									
									
								
							
							
						
						
									
										244
									
								
								src/grid.rs
									
									
									
									
									
								
							| @@ -1,7 +1,11 @@ | |||||||
|  | use core::panic; | ||||||
| use std::error::Error; | use std::error::Error; | ||||||
|  |  | ||||||
| #[derive(Debug)] | #[derive(Debug, PartialEq, Eq)] | ||||||
| pub struct Grid<T: Clone>(pub Vec<Vec<T>>); | pub struct Grid<T: Clone> { | ||||||
|  |     pub rows: Vec<Vec<T>>, | ||||||
|  |     pub width: u32, | ||||||
|  | } | ||||||
|  |  | ||||||
| impl<T: Clone> Grid<T> { | impl<T: Clone> Grid<T> { | ||||||
|     pub fn new(grid: Vec<Vec<T>>) -> Result<Self, Box<dyn Error>> { |     pub fn new(grid: Vec<Vec<T>>) -> Result<Self, Box<dyn Error>> { | ||||||
| @@ -11,23 +15,245 @@ impl<T: Clone> Grid<T> { | |||||||
|                 return Err(Box::from("Rows need to all be equal in length")); |                 return Err(Box::from("Rows need to all be equal in length")); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         Ok(Grid(grid)) |         Ok(Grid { | ||||||
|  |             rows: grid, | ||||||
|  |             width: row_length as u32, | ||||||
|  |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn invert(&mut self) -> Self { |     pub fn rotate_90(&mut self) -> Self { | ||||||
|         let height = self.0.len(); |         let height = self.rows.len(); | ||||||
|         let width = self.0[0].len(); |         let width = self.rows[0].len(); | ||||||
|  |  | ||||||
|         let mut new_grid = Vec::with_capacity(width); |         let mut new_grid = Vec::with_capacity(width); | ||||||
|  |  | ||||||
|         for col_idx in 0..width { |         for col_idx in 0..width { | ||||||
|             let mut new_row = Vec::with_capacity(height); |             let mut new_row = Vec::with_capacity(height); | ||||||
|             for row_idx in 0..height { |             for row_idx in 0..height { | ||||||
|                 new_row.push(self.0[row_idx][col_idx].clone()); |                 new_row.push(self.rows[row_idx][col_idx].clone()); | ||||||
|             } |             } | ||||||
|             new_grid.push(new_row); |             new_grid.push(new_row); | ||||||
|         } |         } | ||||||
|         self.0 = new_grid; |         self.rows = new_grid; | ||||||
|         Grid(self.0.clone()) |         self.width = height as u32; | ||||||
|  |         Grid { | ||||||
|  |             rows: self.rows.clone(), | ||||||
|  |             width: height as u32, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn get_diagonals_aigu(&self) -> Vec<Vec<T>> { | ||||||
|  |         let mut diagonals = Vec::new(); | ||||||
|  |         // col_idx == starting column of this diagonal | ||||||
|  |         for col_idx in 0..self.width { | ||||||
|  |             diagonals.push(self.get_diagonal_aigu(col_idx, 0)); | ||||||
|  |             if col_idx == self.width - 1 { | ||||||
|  |                 // row_idx == starting row of this diagonal | ||||||
|  |                 for row_idx in 1..self.rows.len() as u32 { | ||||||
|  |                     diagonals.push(self.get_diagonal_aigu(col_idx, row_idx)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         diagonals | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn get_diagonal_aigu(&self, starting_col: u32, starting_row: u32) -> Vec<T> { | ||||||
|  |         if starting_col != self.width - 1 && starting_row != 0 { | ||||||
|  |             panic!("Start of diagonal needs to be valid. Start at top row or rightmost column"); | ||||||
|  |         } | ||||||
|  |         // col_idx == current col_idx of this diagonal | ||||||
|  |         let mut col_idx = starting_col as usize; | ||||||
|  |         // row_idx == current row_idx of this diagonal | ||||||
|  |         let mut row_idx = starting_row as usize; | ||||||
|  |  | ||||||
|  |         let mut diagonal = Vec::new(); | ||||||
|  |  | ||||||
|  |         while let Some(row) = self.rows.get(row_idx) { | ||||||
|  |             if let Some(element) = row.get(col_idx) { | ||||||
|  |                 diagonal.push(element.clone()); | ||||||
|  |                 if let Some(sub) = col_idx.checked_sub(1) { | ||||||
|  |                     col_idx = sub; | ||||||
|  |                 } else { | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 row_idx += 1; | ||||||
|  |             } else { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         diagonal.reverse(); | ||||||
|  |         diagonal | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub fn get_diagonals_grave(&self) -> Vec<Vec<T>> { | ||||||
|  |         let mut diagonals = Vec::new(); | ||||||
|  |         // col_idx == starting column of this diagonal | ||||||
|  |         for col_idx in (0..self.width).rev() { | ||||||
|  |             diagonals.push(self.get_diagonal_grave(col_idx, 0)); | ||||||
|  |             if col_idx == 0 { | ||||||
|  |                 // row_idx == starting row of this diagonal | ||||||
|  |                 for row_idx in 1..self.rows.len() as u32 { | ||||||
|  |                     diagonals.push(self.get_diagonal_grave(col_idx, row_idx)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         diagonals | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn get_diagonal_grave(&self, starting_col: u32, starting_row: u32) -> Vec<T> { | ||||||
|  |         if starting_col != 0 && starting_row != 0 { | ||||||
|  |             panic!("Start of diagonal needs to be valid. Start at top row or leftmost column"); | ||||||
|  |         } | ||||||
|  |         // col_idx == current col_idx of this diagonal | ||||||
|  |         let mut col_idx = starting_col as usize; | ||||||
|  |         // row_idx == current row_idx of this diagonal | ||||||
|  |         let mut row_idx = starting_row as usize; | ||||||
|  |  | ||||||
|  |         let mut diagonal = Vec::new(); | ||||||
|  |  | ||||||
|  |         while let Some(row) = self.rows.get(row_idx) { | ||||||
|  |             if let Some(element) = row.get(col_idx) { | ||||||
|  |                 diagonal.push(element.clone()); | ||||||
|  |                 col_idx += 1; | ||||||
|  |                 row_idx += 1; | ||||||
|  |             } else { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         diagonal | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod test { | ||||||
|  |     use super::Grid; | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn diag_aigu_4x4() { | ||||||
|  |         let grid = Grid::new(vec![ | ||||||
|  |             vec!["a", "b", "c", "d"], | ||||||
|  |             vec!["e", "f", "g", "h"], | ||||||
|  |             vec!["i", "j", "k", "l"], | ||||||
|  |             vec!["m", "n", "o", "p"], | ||||||
|  |         ]) | ||||||
|  |         .unwrap(); | ||||||
|  |         let res = vec![ | ||||||
|  |             vec!["a"], | ||||||
|  |             vec!["e", "b"], | ||||||
|  |             vec!["i", "f", "c"], | ||||||
|  |             vec!["m", "j", "g", "d"], | ||||||
|  |             vec!["n", "k", "h"], | ||||||
|  |             vec!["o", "l"], | ||||||
|  |             vec!["p"], | ||||||
|  |         ]; | ||||||
|  |         assert_eq!(res, grid.get_diagonals_aigu()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn diag_aigu_4x3() { | ||||||
|  |         let grid = Grid::new(vec![ | ||||||
|  |             vec!["a", "b", "c", "d"], | ||||||
|  |             vec!["e", "f", "g", "h"], | ||||||
|  |             vec!["i", "j", "k", "l"], | ||||||
|  |         ]) | ||||||
|  |         .unwrap(); | ||||||
|  |         let res = vec![ | ||||||
|  |             vec!["a"], | ||||||
|  |             vec!["e", "b"], | ||||||
|  |             vec!["i", "f", "c"], | ||||||
|  |             vec!["j", "g", "d"], | ||||||
|  |             vec!["k", "h"], | ||||||
|  |             vec!["l"], | ||||||
|  |         ]; | ||||||
|  |         assert_eq!(res, grid.get_diagonals_aigu()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn diag_aigu_3x4() { | ||||||
|  |         let grid = Grid::new(vec![ | ||||||
|  |             vec!["a", "b", "c"], | ||||||
|  |             vec!["d", "e", "f"], | ||||||
|  |             vec!["g", "h", "i"], | ||||||
|  |             vec!["j", "k", "l"], | ||||||
|  |         ]) | ||||||
|  |         .unwrap(); | ||||||
|  |         let res = vec![ | ||||||
|  |             vec!["a"], | ||||||
|  |             vec!["d", "b"], | ||||||
|  |             vec!["g", "e", "c"], | ||||||
|  |             vec!["j", "h", "f"], | ||||||
|  |             vec!["k", "i"], | ||||||
|  |             vec!["l"], | ||||||
|  |         ]; | ||||||
|  |         assert_eq!(res, grid.get_diagonals_aigu()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn diag_grave_4x4() { | ||||||
|  |         let grid = Grid::new(vec![ | ||||||
|  |             vec!["a", "b", "c", "d"], | ||||||
|  |             vec!["e", "f", "g", "h"], | ||||||
|  |             vec!["i", "j", "k", "l"], | ||||||
|  |             vec!["m", "n", "o", "p"], | ||||||
|  |         ]) | ||||||
|  |         .unwrap(); | ||||||
|  |         let res = vec![ | ||||||
|  |             vec!["d"], | ||||||
|  |             vec!["c", "h"], | ||||||
|  |             vec!["b", "g", "l"], | ||||||
|  |             vec!["a", "f", "k", "p"], | ||||||
|  |             vec!["e", "j", "o"], | ||||||
|  |             vec!["i", "n"], | ||||||
|  |             vec!["m"], | ||||||
|  |         ]; | ||||||
|  |         assert_eq!(res, grid.get_diagonals_grave()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn diag_grave_4x3() { | ||||||
|  |         let grid = Grid::new(vec![ | ||||||
|  |             vec!["a", "b", "c", "d"], | ||||||
|  |             vec!["e", "f", "g", "h"], | ||||||
|  |             vec!["i", "j", "k", "l"], | ||||||
|  |         ]) | ||||||
|  |         .unwrap(); | ||||||
|  |         let res = vec![ | ||||||
|  |             vec!["d"], | ||||||
|  |             vec!["c", "h"], | ||||||
|  |             vec!["b", "g", "l"], | ||||||
|  |             vec!["a", "f", "k"], | ||||||
|  |             vec!["e", "j"], | ||||||
|  |             vec!["i"], | ||||||
|  |         ]; | ||||||
|  |         assert_eq!(res, grid.get_diagonals_grave()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn diag_grave_3x4() { | ||||||
|  |         let grid = Grid::new(vec![ | ||||||
|  |             vec!["a", "b", "c"], | ||||||
|  |             vec!["d", "e", "f"], | ||||||
|  |             vec!["g", "h", "i"], | ||||||
|  |             vec!["j", "k", "l"], | ||||||
|  |         ]) | ||||||
|  |         .unwrap(); | ||||||
|  |         let res = vec![ | ||||||
|  |             vec!["c"], | ||||||
|  |             vec!["b", "f"], | ||||||
|  |             vec!["a", "e", "i"], | ||||||
|  |             vec!["d", "h", "l"], | ||||||
|  |             vec!["g", "k"], | ||||||
|  |             vec!["j"], | ||||||
|  |         ]; | ||||||
|  |         assert_eq!(res, grid.get_diagonals_grave()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn rotate() { | ||||||
|  |         let mut grid = Grid::new(vec![vec!["a", "b"], vec!["c", "d"]]).unwrap(); | ||||||
|  |         let res = Grid::new(vec![vec!["a", "c"], vec!["b", "d"]]).unwrap(); | ||||||
|  |         assert_eq!(res, grid.rotate_90()) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,3 +4,4 @@ pub mod grid; | |||||||
| pub mod math; | pub mod math; | ||||||
| pub mod number; | pub mod number; | ||||||
| pub mod permutation; | pub mod permutation; | ||||||
|  | pub mod time; | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ pub enum Sign { | |||||||
|  |  | ||||||
| #[derive(Clone, Debug, Eq, PartialEq, Hash)] | #[derive(Clone, Debug, Eq, PartialEq, Hash)] | ||||||
| pub struct Number { | pub struct Number { | ||||||
|     pub digits: Vec<isize>, |     pub digits: Vec<i8>, | ||||||
|     pub sign: Sign, |     pub sign: Sign, | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -26,9 +26,9 @@ impl Number { | |||||||
|         (n % modulo) / divisor |         (n % modulo) / divisor | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub const fn byte_to_digit(b: u8) -> isize { |     pub const fn byte_to_digit(b: u8) -> i8 { | ||||||
|         // wrapping_sub('0' as u32) same as - 48 but less magical |         // wrapping_sub('0' as u32) same as - 48 but less magical | ||||||
|         (b as isize).wrapping_sub('0' as isize) |         (b as i8).wrapping_sub('0' as i8) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn pow(self, n: u32) -> Self { |     pub fn pow(self, n: u32) -> Self { | ||||||
| @@ -48,17 +48,21 @@ impl Number { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn ten_pow(self, n: u32) -> Self { | ||||||
|  |         Number { | ||||||
|  |             digits: [vec![0; n as usize], self.digits].concat(), | ||||||
|  |             sign: self.sign, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     pub fn fact(self) -> Self { |     pub fn fact(self) -> Self { | ||||||
|         let mut fact = Number::from(1); |         let mut fact = Number::from(1); | ||||||
|         if ((self.digits.len() * 8) as u32) < isize::BITS { |         let mut n = Number::from(1); | ||||||
|             let max = isize::try_from(self).unwrap(); |         while n <= self { | ||||||
|             for n in 1..=max { |             fact *= n.clone(); | ||||||
|                 fact = fact * n; |             n += 1.into(); | ||||||
|         } |         } | ||||||
|         fact |         fact | ||||||
|         } else { |  | ||||||
|             panic!("starting number too big") |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn fib(n: u64) -> Self { |     pub fn fib(n: u64) -> Self { | ||||||
| @@ -71,6 +75,13 @@ impl Number { | |||||||
|  |  | ||||||
|         last_two.0 |         last_two.0 | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn abs(self) -> Self { | ||||||
|  |         Number { | ||||||
|  |             digits: self.digits, | ||||||
|  |             sign: Sign::Positif, | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Display for Number { | impl Display for Number { | ||||||
| @@ -107,4 +118,28 @@ mod number_tests { | |||||||
|         assert_eq!(digit_4, 2); |         assert_eq!(digit_4, 2); | ||||||
|         assert_eq!(digit_5, 1); |         assert_eq!(digit_5, 1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_pow() { | ||||||
|  |         let num = Number::from(2); | ||||||
|  |         assert_eq!(Number::from(16), num.pow(4)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_ten_pow_zero() { | ||||||
|  |         let num = Number::from(2); | ||||||
|  |         assert_eq!(Number::from(2), num.ten_pow(0)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_ten_pow_one() { | ||||||
|  |         let num = Number::from(2); | ||||||
|  |         assert_eq!(Number::from(20), num.ten_pow(1)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_ten_pow_two() { | ||||||
|  |         let num = Number::from(2); | ||||||
|  |         assert_eq!(Number::from(200), num.ten_pow(2)); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| use std::{ | use std::{ | ||||||
|     cmp::min, |     cmp::{min, Ordering}, | ||||||
|     iter::zip, |     iter::zip, | ||||||
|     ops::{Add, AddAssign}, |     ops::{Add, AddAssign}, | ||||||
| }; | }; | ||||||
| @@ -14,9 +14,10 @@ impl Add for Number { | |||||||
|         let rhs_len = rhs.digits.len(); |         let rhs_len = rhs.digits.len(); | ||||||
|         let mut self_digits = self.digits.clone(); |         let mut self_digits = self.digits.clone(); | ||||||
|         let mut rhs_digits = rhs.digits.clone(); |         let mut rhs_digits = rhs.digits.clone(); | ||||||
|  |         let ord = self.clone().abs().cmp(&rhs.clone().abs()); | ||||||
|         if self_len != rhs_len { |         if self_len != rhs_len { | ||||||
|             let difference = (self_len).abs_diff(rhs_len); |             let difference = (self_len).abs_diff(rhs_len); | ||||||
|             let pad = vec![0isize; difference]; |             let pad = vec![0i8; difference]; | ||||||
|             if min(self_len, rhs_len) == self_len { |             if min(self_len, rhs_len) == self_len { | ||||||
|                 self_digits = [self.digits, pad].concat(); |                 self_digits = [self.digits, pad].concat(); | ||||||
|             } else { |             } else { | ||||||
| @@ -26,14 +27,24 @@ impl Add for Number { | |||||||
|         let zipped = zip(self_digits.iter(), rhs_digits.iter()); |         let zipped = zip(self_digits.iter(), rhs_digits.iter()); | ||||||
|         let mut carry = 0; |         let mut carry = 0; | ||||||
|         let mut digits = Vec::new(); |         let mut digits = Vec::new(); | ||||||
|         let mut sign = match (self.sign, rhs.sign) { |         let sign = match (self.sign, rhs.sign, ord) { | ||||||
|             (Sign::Positif, Sign::Positif) => Sign::Positif, |             (Sign::Positif, Sign::Positif, _) => Sign::Positif, | ||||||
|             (Sign::Negatif, Sign::Negatif) => Sign::Negatif, |             (Sign::Negatif, Sign::Negatif, _) => Sign::Negatif, | ||||||
|             (Sign::Positif, Sign::Negatif) | (Sign::Negatif, Sign::Positif) => Sign::Positif, |             (Sign::Positif, Sign::Negatif, Ordering::Greater) => Sign::Positif, | ||||||
|  |             (Sign::Positif, Sign::Negatif, Ordering::Less) => Sign::Negatif, | ||||||
|  |             (Sign::Negatif, Sign::Positif, Ordering::Greater) => Sign::Negatif, | ||||||
|  |             (Sign::Negatif, Sign::Positif, Ordering::Less) => Sign::Positif, | ||||||
|  |             (Sign::Positif, Sign::Negatif, Ordering::Equal) | ||||||
|  |             | (Sign::Negatif, Sign::Positif, Ordering::Equal) => Sign::Positif, | ||||||
|         }; |         }; | ||||||
|         for (a, b) in zipped { |         for (a, b) in zipped { | ||||||
|             let comb = match (self.sign, rhs.sign) { |             let comb = match (self.sign, rhs.sign, ord) { | ||||||
|                 (Sign::Positif, Sign::Positif) => { |                 (Sign::Positif, Sign::Negatif, Ordering::Equal) | ||||||
|  |                 | (Sign::Negatif, Sign::Positif, Ordering::Equal) => { | ||||||
|  |                     digits.push(0); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 (Sign::Positif, Sign::Positif, _) | (Sign::Negatif, Sign::Negatif, _) => { | ||||||
|                     let comb = a + b + carry; |                     let comb = a + b + carry; | ||||||
|                     if comb > 9 { |                     if comb > 9 { | ||||||
|                         carry = 1; |                         carry = 1; | ||||||
| @@ -42,43 +53,32 @@ impl Add for Number { | |||||||
|                     } |                     } | ||||||
|                     comb % 10 |                     comb % 10 | ||||||
|                 } |                 } | ||||||
|                 (Sign::Positif, Sign::Negatif) => { |                 (Sign::Positif, Sign::Negatif, Ordering::Greater) | ||||||
|  |                 | (Sign::Negatif, Sign::Positif, Ordering::Greater) => { | ||||||
|  |                     let comb = if b > &(a - carry) { | ||||||
|  |                         let comb = a + 10 - b - carry; | ||||||
|  |                         carry = 1; | ||||||
|  |                         comb | ||||||
|  |                     } else { | ||||||
|                         let comb = a - b - carry; |                         let comb = a - b - carry; | ||||||
|                     if comb > 0 && b > a { |  | ||||||
|                         carry = 1; |  | ||||||
|                     } else { |  | ||||||
|                         carry = 0; |                         carry = 0; | ||||||
|                     } |                         comb | ||||||
|                     if b > a { |                     }; | ||||||
|                         sign = Sign::Negatif; |  | ||||||
|                     } else { |  | ||||||
|                         sign = Sign::Positif; |  | ||||||
|                     } |  | ||||||
|                     (comb % 10).abs() |                     (comb % 10).abs() | ||||||
|                 } |                 } | ||||||
|                 (Sign::Negatif, Sign::Positif) => { |                 (Sign::Positif, Sign::Negatif, Ordering::Less) | ||||||
|                     let comb = -a + b - carry; |                 | (Sign::Negatif, Sign::Positif, Ordering::Less) => { | ||||||
|                     if comb > 0 && a > b { |                     let comb = if a > &(b - carry) { | ||||||
|  |                         let comb = b + 10 - a - carry; | ||||||
|                         carry = 1; |                         carry = 1; | ||||||
|  |                         comb | ||||||
|                     } else { |                     } else { | ||||||
|  |                         let comb = b - a - carry; | ||||||
|                         carry = 0; |                         carry = 0; | ||||||
|                     } |                         comb | ||||||
|                     if a > b { |                     }; | ||||||
|                         sign = Sign::Negatif; |  | ||||||
|                     } else { |  | ||||||
|                         sign = Sign::Positif; |  | ||||||
|                     } |  | ||||||
|                     (comb % 10).abs() |                     (comb % 10).abs() | ||||||
|                 } |                 } | ||||||
|                 (Sign::Negatif, Sign::Negatif) => { |  | ||||||
|                     let comb = a + b + carry; |  | ||||||
|                     if comb > 9 { |  | ||||||
|                         carry = 1; |  | ||||||
|                     } else { |  | ||||||
|                         carry = 0; |  | ||||||
|                     } |  | ||||||
|                     comb % 10 |  | ||||||
|                 } |  | ||||||
|             }; |             }; | ||||||
|             digits.push(comb); |             digits.push(comb); | ||||||
|         } |         } | ||||||
| @@ -87,6 +87,13 @@ impl Add for Number { | |||||||
|             digits.push(carry); |             digits.push(carry); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         for &digit in digits.clone().iter().rev() { | ||||||
|  |             if digit != 0 || digits.len() == 1 { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             digits.pop(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         Self { digits, sign } |         Self { digits, sign } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -104,13 +111,21 @@ mod test_number_add { | |||||||
|     use crate::number::Number; |     use crate::number::Number; | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn add_positif() { |     fn add_positif_1() { | ||||||
|         let a = Number::from(1); |         let a = Number::from(1); | ||||||
|         let b = 1.into(); |         let b = 1.into(); | ||||||
|         let res = Number::from(2); |         let res = Number::from(2); | ||||||
|         assert_eq!(res, a + b); |         assert_eq!(res, a + b); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn add_positif_2() { | ||||||
|  |         let a = Number::from(9); | ||||||
|  |         let b = 1.into(); | ||||||
|  |         let res = Number::from(10); | ||||||
|  |         assert_eq!(res, a + b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn add_large_positif() { |     fn add_large_positif() { | ||||||
|         let a = Number::from(9); |         let a = Number::from(9); | ||||||
| @@ -152,21 +167,36 @@ mod test_number_add { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn add_larger_positif_to_negatif() { |     fn add_larger_positif_to_negatif_1() { | ||||||
|         let a = Number::from(-1); |         let a = Number::from(-1); | ||||||
|         let b = (11).into(); |         let b = (11).into(); | ||||||
|         let res = Number::from(10); |         let res = Number::from(10); | ||||||
|         assert_eq!(res, a + b); |         assert_eq!(res, a + b); | ||||||
|     } |     } | ||||||
|  |     #[test] | ||||||
|  |     fn add_larger_positif_to_negatif_2() { | ||||||
|  |         let a = Number::from(-2); | ||||||
|  |         let b = (11).into(); | ||||||
|  |         let res = Number::from(9); | ||||||
|  |         assert_eq!(res, a + b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn add_larger_negatif_to_positif() { |     fn add_larger_negatif_to_positif_1() { | ||||||
|         let a = Number::from(1); |         let a = Number::from(1); | ||||||
|         let b = (-11).into(); |         let b = (-11).into(); | ||||||
|         let res = Number::from(-10); |         let res = Number::from(-10); | ||||||
|         assert_eq!(res, a + b); |         assert_eq!(res, a + b); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn add_larger_negatif_to_positif_2() { | ||||||
|  |         let a = Number::from(2); | ||||||
|  |         let b = (-11).into(); | ||||||
|  |         let res = Number::from(-9); | ||||||
|  |         assert_eq!(res, a + b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn add_positif_to_larger_negatif() { |     fn add_positif_to_larger_negatif() { | ||||||
|         let a = Number::from(-99); |         let a = Number::from(-99); | ||||||
|   | |||||||
| @@ -7,54 +7,93 @@ use std::{ | |||||||
| use super::{Number, Sign}; | use super::{Number, Sign}; | ||||||
|  |  | ||||||
| impl Number { | impl Number { | ||||||
|     pub fn div_with_rem(n1: Number, n2: Number) -> Result<(Number, Number), Box<dyn Error>> { |     pub fn div_with_rem( | ||||||
|         if n2 == 0.into() { |         dividend: Number, | ||||||
|  |         divisor: Number, | ||||||
|  |     ) -> Result<(Number, Number), Box<dyn Error>> { | ||||||
|  |         if divisor == 0.into() { | ||||||
|             return Err(Box::from("Division by 0")); |             return Err(Box::from("Division by 0")); | ||||||
|         } |         } | ||||||
|         let n1_len = n1.digits.len(); |         let dividend_len = dividend.digits.len(); | ||||||
|         let n2_len = n2.digits.len(); |         let divisor_len = divisor.digits.len(); | ||||||
|         if n2_len > n1_len { |         let sign = match (dividend.sign, divisor.sign) { | ||||||
|             return Ok((Number::from(0), n2)); |             (Sign::Positif, Sign::Positif) | (Sign::Negatif, Sign::Negatif) => Sign::Positif, | ||||||
|         } |             (Sign::Positif, Sign::Negatif) | (Sign::Negatif, Sign::Positif) => Sign::Negatif, | ||||||
|         let dividend = n1.digits[..n2_len].to_vec(); |         }; | ||||||
|         let mut quotient = vec![]; |         let mut dividend = Number { | ||||||
|         let mut remainder = Number { |             digits: dividend.digits, | ||||||
|             digits: dividend.clone(), |  | ||||||
|             sign: Sign::Positif, |             sign: Sign::Positif, | ||||||
|         }; |         }; | ||||||
|         let mut iteration = 1; |         let divisor = Number { | ||||||
|  |             digits: divisor.digits, | ||||||
|  |             sign: Sign::Positif, | ||||||
|  |         }; | ||||||
|  |         match (sign, dividend.cmp(&divisor)) { | ||||||
|  |             (_, std::cmp::Ordering::Less) => return Ok((Number::from(0), dividend)), | ||||||
|  |             (Sign::Positif, std::cmp::Ordering::Equal) => { | ||||||
|  |                 return Ok((Number::from(1), Number::from(0))) | ||||||
|  |             } | ||||||
|  |             (Sign::Negatif, std::cmp::Ordering::Equal) => { | ||||||
|  |                 return Ok((Number::from(-1), Number::from(0))) | ||||||
|  |             } | ||||||
|  |             (_, std::cmp::Ordering::Greater) => (), | ||||||
|  |         } | ||||||
|  |         let mut quotient = vec![]; | ||||||
|  |         let mut remainder = Number { | ||||||
|  |             digits: dividend | ||||||
|  |                 .digits | ||||||
|  |                 .drain((dividend_len - divisor_len)..) | ||||||
|  |                 .collect(), | ||||||
|  |             sign: Sign::Positif, | ||||||
|  |         }; | ||||||
|  |  | ||||||
|         loop { |         loop { | ||||||
|  |             while remainder < divisor && !dividend.digits.is_empty() { | ||||||
|  |                 remainder.digits.insert(0, dividend.digits.pop().unwrap()); | ||||||
|  |                 quotient.push(0); | ||||||
|  |             } | ||||||
|             let mut factor = 0; |             let mut factor = 0; | ||||||
|             loop { |             loop { | ||||||
|                 let temp_remainder = remainder.clone() - n2.clone(); |                 if remainder.digits.iter().max().unwrap() == &0 { | ||||||
|  |                     quotient.push(0); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 let temp_remainder = remainder.clone() - divisor.clone(); | ||||||
|                 if temp_remainder.sign == Sign::Negatif { |                 if temp_remainder.sign == Sign::Negatif { | ||||||
|                     quotient.push(factor); |                     quotient.push(factor); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 remainder = temp_remainder; |  | ||||||
|                 factor += 1; |                 factor += 1; | ||||||
|             } |                 if temp_remainder == 0.into() { | ||||||
|             if n1_len == n2_len + iteration - 1 { |                     remainder = temp_remainder; | ||||||
|  |                     quotient.push(factor); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|             remainder.digits.push(n1.digits[n2_len + iteration - 1]); |                 remainder = temp_remainder; | ||||||
|             iteration += 1; |  | ||||||
|             } |             } | ||||||
|         let mut res = Number { |             if dividend.digits.is_empty() { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             remainder.digits.insert(0, dividend.digits.pop().unwrap()); | ||||||
|  |         } | ||||||
|  |         for digit in quotient.clone() { | ||||||
|  |             if digit != 0 || quotient.len() == 1 { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             quotient.remove(0); | ||||||
|  |         } | ||||||
|  |         quotient.reverse(); | ||||||
|  |         let res = Number { | ||||||
|             digits: quotient, |             digits: quotient, | ||||||
|             sign: Sign::Positif, |             sign, | ||||||
|         }; |         }; | ||||||
|         for digit in res.clone().digits { |         let mut rem_digits = remainder.clone().digits; | ||||||
|             if digit != 0 || res.digits.len() == 1 { |         rem_digits.reverse(); | ||||||
|                 break; |         for digit in rem_digits { | ||||||
|             } |  | ||||||
|             res.digits.remove(0); |  | ||||||
|         } |  | ||||||
|         for digit in remainder.clone().digits { |  | ||||||
|             if digit != 0 || remainder.digits.len() == 1 { |             if digit != 0 || remainder.digits.len() == 1 { | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             remainder.digits.remove(0); |             remainder.digits.pop(); | ||||||
|         } |         } | ||||||
|         Ok((res, remainder)) |         Ok((res, remainder)) | ||||||
|     } |     } | ||||||
| @@ -110,3 +149,107 @@ impl RemAssign for Number { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod test_number_div_rem { | ||||||
|  |     use core::panic; | ||||||
|  |  | ||||||
|  |     use crate::number::Number; | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn zero_denominator() { | ||||||
|  |         let a = Number::from(9); | ||||||
|  |         let b = Number::from(0); | ||||||
|  |         if Number::div_with_rem(a, b).is_ok() { | ||||||
|  |             panic!("Division by 0 not allowed"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_positif() { | ||||||
|  |         let a = Number::from(9); | ||||||
|  |         let b = Number::from(9); | ||||||
|  |         let res = (Number::from(1), Number::from(0)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_negatif() { | ||||||
|  |         let a = Number::from(-9); | ||||||
|  |         let b = Number::from(-9); | ||||||
|  |         let res = (Number::from(1), Number::from(0)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_positif_with_negatif() { | ||||||
|  |         let a = Number::from(9); | ||||||
|  |         let b = Number::from(-9); | ||||||
|  |         let res = (Number::from(-1), Number::from(0)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_negatif_with_positif() { | ||||||
|  |         let a = Number::from(-9); | ||||||
|  |         let b = Number::from(9); | ||||||
|  |         let res = (Number::from(-1), Number::from(0)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_eleven_x_ten() { | ||||||
|  |         let a = Number::from(11); | ||||||
|  |         let b = Number::from(10); | ||||||
|  |         let res = (Number::from(1), Number::from(1)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_eleven_x_eleven() { | ||||||
|  |         let a = Number::from(11); | ||||||
|  |         let b = Number::from(11); | ||||||
|  |         let res = (Number::from(1), Number::from(0)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_ten_x_eleven() { | ||||||
|  |         let a = Number::from(10); | ||||||
|  |         let b = Number::from(11); | ||||||
|  |         let res = (Number::from(0), Number::from(10)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_big_1() { | ||||||
|  |         let a = Number::from("123"); | ||||||
|  |         let b = Number::from("32"); | ||||||
|  |         let res = (Number::from(3), Number::from(27)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_big_2() { | ||||||
|  |         let a = Number::from("123456789"); | ||||||
|  |         let b = Number::from("123"); | ||||||
|  |         let res = (Number::from(1003713), Number::from(90)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_big_3() { | ||||||
|  |         let a = Number::from("1010101010"); | ||||||
|  |         let b = Number::from("1010"); | ||||||
|  |         let res = (Number::from(1000100), Number::from(10)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn div_rem_small() { | ||||||
|  |         let a = Number::from(10); | ||||||
|  |         let b = Number::from(1); | ||||||
|  |         let res = (Number::from(10), Number::from(0)); | ||||||
|  |         assert_eq!(res, Number::div_with_rem(a, b).unwrap()); | ||||||
|  |     } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ impl TryFrom<Number> for isize { | |||||||
|     fn try_from(value: Number) -> Result<Self, Self::Error> { |     fn try_from(value: Number) -> Result<Self, Self::Error> { | ||||||
|         let mut num = 0; |         let mut num = 0; | ||||||
|         for (pos, &digit) in value.digits.iter().enumerate() { |         for (pos, &digit) in value.digits.iter().enumerate() { | ||||||
|             let mul = digit.checked_mul(10isize.pow(pos as u32)); |             let mul = (digit as isize).checked_mul(10isize.pow(pos as u32)); | ||||||
|             if mul.is_none() { |             if mul.is_none() { | ||||||
|                 return Err(Box::from("Cannot convert Number to isize. Too big.")); |                 return Err(Box::from("Cannot convert Number to isize. Too big.")); | ||||||
|             } |             } | ||||||
| @@ -62,7 +62,7 @@ impl From<isize> for Number { | |||||||
|         let num_len = (value as f64 + 1.0).log10().ceil() as usize; |         let num_len = (value as f64 + 1.0).log10().ceil() as usize; | ||||||
|         let mut digits = vec![]; |         let mut digits = vec![]; | ||||||
|         for digit_idx in 0..num_len { |         for digit_idx in 0..num_len { | ||||||
|             let digit = Self::get_digit(value, digit_idx); |             let digit = Self::get_digit(value, digit_idx) as i8; | ||||||
|             digits.push(digit); |             digits.push(digit); | ||||||
|         } |         } | ||||||
|         let digits = digits.to_vec(); |         let digits = digits.to_vec(); | ||||||
|   | |||||||
| @@ -7,42 +7,43 @@ impl Mul for Number { | |||||||
|  |  | ||||||
|     #[allow(clippy::suspicious_arithmetic_impl)] |     #[allow(clippy::suspicious_arithmetic_impl)] | ||||||
|     fn mul(self, rhs: Self) -> Self::Output { |     fn mul(self, rhs: Self) -> Self::Output { | ||||||
|         println!("left {self:#?}"); |  | ||||||
|         println!("right {rhs:#?}"); |  | ||||||
|         let mut mult_vecs = Vec::new(); |  | ||||||
|         let sign = match (self.sign, rhs.sign) { |         let sign = match (self.sign, rhs.sign) { | ||||||
|             (Sign::Positif, Sign::Positif) => Sign::Positif, |             (Sign::Positif, Sign::Positif) => Sign::Positif, | ||||||
|             (Sign::Positif, Sign::Negatif) => Sign::Negatif, |             (Sign::Positif, Sign::Negatif) => Sign::Negatif, | ||||||
|             (Sign::Negatif, Sign::Positif) => Sign::Negatif, |             (Sign::Negatif, Sign::Positif) => Sign::Negatif, | ||||||
|             (Sign::Negatif, Sign::Negatif) => Sign::Positif, |             (Sign::Negatif, Sign::Negatif) => Sign::Positif, | ||||||
|         }; |         }; | ||||||
|         for (idx, rdigit) in rhs.digits.iter().enumerate() { |         let mut digits = Vec::new(); | ||||||
|             let rdigit = rdigit * 10_isize.pow(idx as u32); |         for (zeroes, rdigit) in rhs.digits.iter().enumerate() { | ||||||
|             let mult_vec: Vec<isize> = self.digits.iter().map(|ldigit| ldigit * rdigit).collect(); |             for (idx, ldigit) in self.digits.iter().enumerate() { | ||||||
|             let mut normalized_mult_vec = Vec::new(); |                 let mult = rdigit * ldigit; | ||||||
|             let mut carry = 0; |                 let new = mult % 10; | ||||||
|             let mut add_zero = true; |                 let mut carry = mult / 10; | ||||||
|             mult_vec.into_iter().for_each(|digit| { |                 if let Some(old) = digits.get(zeroes + idx) { | ||||||
|                 let digit = digit + carry; |                     let add = old + new; | ||||||
|                 if digit > 9 { |                     digits[zeroes + idx] = add % 10; | ||||||
|                     carry = digit % 10; |                     carry += add / 10; | ||||||
|                     normalized_mult_vec.insert(0, digit / 10); |  | ||||||
|                 } else { |                 } else { | ||||||
|                     normalized_mult_vec.insert(0, digit); |                     digits.push(new); | ||||||
|                     carry = 0; |  | ||||||
|                     add_zero = false; |  | ||||||
|                 } |                 } | ||||||
|             }); |                 let mut carry_idx = 1; | ||||||
|             if carry != 0 || add_zero { |                 loop { | ||||||
|                 normalized_mult_vec.insert(0, carry); |                     if carry == 0 { | ||||||
|  |                         break; | ||||||
|                     } |                     } | ||||||
|             mult_vecs.push(Number { |                     if let Some(old) = digits.get(zeroes + idx + carry_idx) { | ||||||
|                 digits: normalized_mult_vec, |                         let add = old + carry; | ||||||
|                 sign, |                         digits[zeroes + idx + carry_idx] = add % 10; | ||||||
|             }); |                         carry = add / 10; | ||||||
|  |                     } else { | ||||||
|  |                         digits.push(carry % 10); | ||||||
|  |                         carry /= 10; | ||||||
|                     } |                     } | ||||||
|  |                     carry_idx += 1; | ||||||
|         mult_vecs.into_iter().reduce(|acc, num| acc + num).unwrap() |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         Number { digits, sign } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -123,7 +124,23 @@ mod test_number_mul { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn mul_big() { |     fn mul_999_x_999() { | ||||||
|  |         let a = Number::from(999); | ||||||
|  |         let b = Number::from(999); | ||||||
|  |         let res = Number::from(998001); | ||||||
|  |         assert_eq!(res, a * b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn mul_big_1() { | ||||||
|  |         let a = Number::from("123"); | ||||||
|  |         let b = Number::from("321"); | ||||||
|  |         let res = Number::from("39483"); | ||||||
|  |         assert_eq!(res, a * b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn mul_big_2() { | ||||||
|         let a = Number::from("123456789"); |         let a = Number::from("123456789"); | ||||||
|         let b = Number::from("987654321"); |         let b = Number::from("987654321"); | ||||||
|         let res = Number::from("121932631112635269"); |         let res = Number::from("121932631112635269"); | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ impl Ord for Number { | |||||||
|                 Sign::Negatif => Ordering::Less, |                 Sign::Negatif => Ordering::Less, | ||||||
|             }, |             }, | ||||||
|             Ordering::Equal => { |             Ordering::Equal => { | ||||||
|                 for pair in zip(&self.digits, &other.digits) { |                 for pair in zip(&self.digits, &other.digits).rev() { | ||||||
|                     return match pair.0.cmp(pair.1) { |                     return match pair.0.cmp(pair.1) { | ||||||
|                         Ordering::Less => match self.sign { |                         Ordering::Less => match self.sign { | ||||||
|                             Sign::Positif => Ordering::Less, |                             Sign::Positif => Ordering::Less, | ||||||
| @@ -46,6 +46,8 @@ impl Ord for Number { | |||||||
|  |  | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod test_number_ord { | mod test_number_ord { | ||||||
|  |     use std::cmp::Ordering; | ||||||
|  |  | ||||||
|     use crate::number::Number; |     use crate::number::Number; | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -53,6 +55,7 @@ mod test_number_ord { | |||||||
|         let a = Number::from(1); |         let a = Number::from(1); | ||||||
|         let b = Number::from(1); |         let b = Number::from(1); | ||||||
|         assert_eq!(a, b); |         assert_eq!(a, b); | ||||||
|  |         assert_eq!(Ordering::Equal, a.cmp(&b)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -60,6 +63,7 @@ mod test_number_ord { | |||||||
|         let a = Number::from(-1); |         let a = Number::from(-1); | ||||||
|         let b = Number::from(-1); |         let b = Number::from(-1); | ||||||
|         assert_eq!(a, b); |         assert_eq!(a, b); | ||||||
|  |         assert_eq!(Ordering::Equal, a.cmp(&b)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -67,6 +71,7 @@ mod test_number_ord { | |||||||
|         let a = Number::from(1); |         let a = Number::from(1); | ||||||
|         let b = Number::from(-1); |         let b = Number::from(-1); | ||||||
|         assert!(a > b); |         assert!(a > b); | ||||||
|  |         assert_eq!(Ordering::Greater, a.cmp(&b)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -74,6 +79,7 @@ mod test_number_ord { | |||||||
|         let a = Number::from(-1); |         let a = Number::from(-1); | ||||||
|         let b = Number::from(1); |         let b = Number::from(1); | ||||||
|         assert!(a < b); |         assert!(a < b); | ||||||
|  |         assert_eq!(Ordering::Less, a.cmp(&b)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -81,6 +87,7 @@ mod test_number_ord { | |||||||
|         let a = Number::from(-1); |         let a = Number::from(-1); | ||||||
|         let b = Number::from(-10); |         let b = Number::from(-10); | ||||||
|         assert!(a > b); |         assert!(a > b); | ||||||
|  |         assert_eq!(Ordering::Greater, a.cmp(&b)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -88,6 +95,7 @@ mod test_number_ord { | |||||||
|         let a = Number::from(1); |         let a = Number::from(1); | ||||||
|         let b = Number::from(10); |         let b = Number::from(10); | ||||||
|         assert!(a < b); |         assert!(a < b); | ||||||
|  |         assert_eq!(Ordering::Less, a.cmp(&b)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -95,6 +103,7 @@ mod test_number_ord { | |||||||
|         let a = Number::from(-10); |         let a = Number::from(-10); | ||||||
|         let b = Number::from(-1); |         let b = Number::from(-1); | ||||||
|         assert!(a < b); |         assert!(a < b); | ||||||
|  |         assert_eq!(Ordering::Less, a.cmp(&b)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
| @@ -102,5 +111,14 @@ mod test_number_ord { | |||||||
|         let a = Number::from(10); |         let a = Number::from(10); | ||||||
|         let b = Number::from(1); |         let b = Number::from(1); | ||||||
|         assert!(a > b); |         assert!(a > b); | ||||||
|  |         assert_eq!(Ordering::Greater, a.cmp(&b)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn test_cmp_91_32() { | ||||||
|  |         let a = Number::from(91); | ||||||
|  |         let b = Number::from(32); | ||||||
|  |         assert!(a > b); | ||||||
|  |         assert_eq!(Ordering::Greater, a.cmp(&b)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| use std::{ | use std::{ | ||||||
|     cmp::min, |     cmp::{min, Ordering}, | ||||||
|     iter::zip, |     iter::zip, | ||||||
|     ops::{Sub, SubAssign}, |     ops::{Sub, SubAssign}, | ||||||
| }; | }; | ||||||
| @@ -14,9 +14,10 @@ impl Sub for Number { | |||||||
|         let rhs_len = rhs.digits.len(); |         let rhs_len = rhs.digits.len(); | ||||||
|         let mut self_digits = self.digits.clone(); |         let mut self_digits = self.digits.clone(); | ||||||
|         let mut rhs_digits = rhs.digits.clone(); |         let mut rhs_digits = rhs.digits.clone(); | ||||||
|  |         let ord = self.clone().abs().cmp(&rhs.clone().abs()); | ||||||
|         if self_len != rhs_len { |         if self_len != rhs_len { | ||||||
|             let difference = (self_len).abs_diff(rhs_len); |             let difference = (self_len).abs_diff(rhs_len); | ||||||
|             let pad = vec![0isize; difference]; |             let pad = vec![0i8; difference]; | ||||||
|             if min(self_len, rhs_len) == self_len { |             if min(self_len, rhs_len) == self_len { | ||||||
|                 self_digits = [self.digits, pad].concat(); |                 self_digits = [self.digits, pad].concat(); | ||||||
|             } else { |             } else { | ||||||
| @@ -26,28 +27,24 @@ impl Sub for Number { | |||||||
|         let zipped = zip(self_digits.iter(), rhs_digits.iter()); |         let zipped = zip(self_digits.iter(), rhs_digits.iter()); | ||||||
|         let mut carry = 0; |         let mut carry = 0; | ||||||
|         let mut digits = Vec::new(); |         let mut digits = Vec::new(); | ||||||
|         let mut sign = match (self.sign, rhs.sign) { |         let sign = match (self.sign, rhs.sign, ord) { | ||||||
|             (Sign::Positif, Sign::Negatif) => Sign::Positif, |             (Sign::Positif, Sign::Negatif, _) => Sign::Positif, | ||||||
|             (Sign::Negatif, Sign::Positif) => Sign::Negatif, |             (Sign::Negatif, Sign::Positif, _) => Sign::Negatif, | ||||||
|             (Sign::Positif, Sign::Positif) | (Sign::Negatif, Sign::Negatif) => Sign::Positif, |             (Sign::Positif, Sign::Positif, Ordering::Greater) => Sign::Positif, | ||||||
|  |             (Sign::Positif, Sign::Positif, Ordering::Less) => Sign::Negatif, | ||||||
|  |             (Sign::Negatif, Sign::Negatif, Ordering::Greater) => Sign::Negatif, | ||||||
|  |             (Sign::Negatif, Sign::Negatif, Ordering::Less) => Sign::Positif, | ||||||
|  |             (Sign::Positif, Sign::Positif, Ordering::Equal) | ||||||
|  |             | (Sign::Negatif, Sign::Negatif, Ordering::Equal) => Sign::Positif, | ||||||
|         }; |         }; | ||||||
|         for (a, b) in zipped { |         for (a, b) in zipped { | ||||||
|             let comb = match (self.sign, rhs.sign) { |             let comb = match (self.sign, rhs.sign, ord) { | ||||||
|                 (Sign::Positif, Sign::Positif) => { |                 (Sign::Positif, Sign::Positif, Ordering::Equal) | ||||||
|                     let comb = a - b - carry; |                 | (Sign::Negatif, Sign::Negatif, Ordering::Equal) => { | ||||||
|                     if comb < 0 { |                     digits.push(0); | ||||||
|                         carry = 1; |                     break; | ||||||
|                     } else { |  | ||||||
|                         carry = 0; |  | ||||||
|                 } |                 } | ||||||
|                     if b > a { |                 (Sign::Positif, Sign::Negatif, _) | (Sign::Negatif, Sign::Positif, _) => { | ||||||
|                         sign = Sign::Negatif; |  | ||||||
|                     } else { |  | ||||||
|                         sign = Sign::Positif; |  | ||||||
|                     } |  | ||||||
|                     (comb % 10).abs() |  | ||||||
|                 } |  | ||||||
|                 (Sign::Positif, Sign::Negatif) => { |  | ||||||
|                     let comb = a + b + carry; |                     let comb = a + b + carry; | ||||||
|                     if comb > 9 { |                     if comb > 9 { | ||||||
|                         carry = 1; |                         carry = 1; | ||||||
| @@ -56,36 +53,47 @@ impl Sub for Number { | |||||||
|                     } |                     } | ||||||
|                     comb % 10 |                     comb % 10 | ||||||
|                 } |                 } | ||||||
|                 (Sign::Negatif, Sign::Positif) => { |                 (Sign::Positif, Sign::Positif, Ordering::Greater) | ||||||
|                     let comb = -a - b - carry; |                 | (Sign::Negatif, Sign::Negatif, Ordering::Greater) => { | ||||||
|                     if comb < -9 { |                     let comb = if b > &(a - carry) { | ||||||
|  |                         let comb = a + 10 - b - carry; | ||||||
|                         carry = 1; |                         carry = 1; | ||||||
|  |                         comb | ||||||
|                     } else { |                     } else { | ||||||
|  |                         let comb = a - b - carry; | ||||||
|                         carry = 0; |                         carry = 0; | ||||||
|                     } |                         comb | ||||||
|  |                     }; | ||||||
|                     (comb % 10).abs() |                     (comb % 10).abs() | ||||||
|                 } |                 } | ||||||
|                 (Sign::Negatif, Sign::Negatif) => { |                 (Sign::Positif, Sign::Positif, Ordering::Less) | ||||||
|                     let comb = -a + b + carry; |                 | (Sign::Negatif, Sign::Negatif, Ordering::Less) => { | ||||||
|                     if comb > 10 { |                     let comb = if a > &(b - carry) { | ||||||
|  |                         let comb = b + 10 - a - carry; | ||||||
|                         carry = 1; |                         carry = 1; | ||||||
|  |                         comb | ||||||
|                     } else { |                     } else { | ||||||
|  |                         let comb = b - a - carry; | ||||||
|                         carry = 0; |                         carry = 0; | ||||||
|                     } |                         comb | ||||||
|                     if a > b { |                     }; | ||||||
|                         sign = Sign::Negatif; |                     (comb % 10).abs() | ||||||
|                     } else { |  | ||||||
|                         sign = Sign::Positif; |  | ||||||
|                     } |  | ||||||
|                     comb % 10 |  | ||||||
|                 } |                 } | ||||||
|             }; |             }; | ||||||
|             digits.push(comb); |             digits.push(comb); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if carry != 0 { |         if carry != 0 { | ||||||
|             digits.push(carry); |             digits.push(carry); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         for &digit in digits.clone().iter().rev() { | ||||||
|  |             if digit != 0 || digits.len() == 1 { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             digits.pop(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         Self { digits, sign } |         Self { digits, sign } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -150,6 +158,38 @@ mod test_number_sub { | |||||||
|         assert_eq!(res, a - b); |         assert_eq!(res, a - b); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn sub_larger_positif_from_positif_1() { | ||||||
|  |         let a = Number::from(1); | ||||||
|  |         let b = (11).into(); | ||||||
|  |         let res = Number::from(-10); | ||||||
|  |         assert_eq!(res, a - b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn sub_larger_positif_from_positif_2() { | ||||||
|  |         let a = Number::from(2); | ||||||
|  |         let b = (11).into(); | ||||||
|  |         let res = Number::from(-9); | ||||||
|  |         assert_eq!(res, a - b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn sub_positif_from_larger_positif_1() { | ||||||
|  |         let a = Number::from(11); | ||||||
|  |         let b = (1).into(); | ||||||
|  |         let res = Number::from(10); | ||||||
|  |         assert_eq!(res, a - b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn sub_positif_from_larger_positif_2() { | ||||||
|  |         let a = Number::from(11); | ||||||
|  |         let b = (2).into(); | ||||||
|  |         let res = Number::from(9); | ||||||
|  |         assert_eq!(res, a - b); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn sub_positif_from_larger_negatif() { |     fn sub_positif_from_larger_negatif() { | ||||||
|         let a = Number::from(-99); |         let a = Number::from(-99); | ||||||
| @@ -165,4 +205,12 @@ mod test_number_sub { | |||||||
|         let res = Number::from(110); |         let res = Number::from(110); | ||||||
|         assert_eq!(res, a - b); |         assert_eq!(res, a - b); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn sub_91_32() { | ||||||
|  |         let a = Number::from(91); | ||||||
|  |         let b = (32).into(); | ||||||
|  |         let res = Number::from(59); | ||||||
|  |         assert_eq!(res, a - b); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,9 +1,11 @@ | |||||||
| use std::error::Error; | use std::error::Error; | ||||||
|  |  | ||||||
| fn factorial(num: usize) -> usize { | use crate::number::Number; | ||||||
|     let mut fact = 1; |  | ||||||
|  | fn factorial(num: usize) -> Number { | ||||||
|  |     let mut fact = Number::from(1); | ||||||
|     for n in 1..=num { |     for n in 1..=num { | ||||||
|         fact *= n; |         fact *= Number::from(n as isize); | ||||||
|     } |     } | ||||||
|     fact |     fact | ||||||
| } | } | ||||||
| @@ -25,59 +27,102 @@ pub fn nth_lex<T: Clone + Ord>(mut digits: Vec<T>, nth: usize) -> Result<Vec<T>, | |||||||
|     if nth == 1 { |     if nth == 1 { | ||||||
|         return Ok(digits); |         return Ok(digits); | ||||||
|     } |     } | ||||||
|     if nth > factorial(digits.len()) || nth == 0 { |     let nth = Number::from(nth as isize); | ||||||
|  |     if nth > factorial(digits.len()) || nth == Number::from(0) { | ||||||
|         return Err(Box::from("Out of bounds")); |         return Err(Box::from("Out of bounds")); | ||||||
|     } |     } | ||||||
|     let mut perm = Vec::new(); |     let mut perm = Vec::new(); | ||||||
|     let num_unique_digits = digits.len(); |     let num_unique_digits = digits.len(); | ||||||
|     let mut remainder = nth - 1; |     let mut remainder = nth - 1.into(); | ||||||
|     for idx in 1..=digits.len() { |     for idx in 1..=digits.len() { | ||||||
|         let permutations = remainder / factorial(num_unique_digits - idx); |         let permutations = remainder.clone() / factorial(num_unique_digits - idx); | ||||||
|         remainder %= factorial(num_unique_digits - idx); |         remainder %= factorial(num_unique_digits - idx); | ||||||
|         perm.push(digits[permutations].clone()); |         let permutations: isize = permutations.try_into().unwrap(); | ||||||
|         digits.remove(permutations); |         perm.push(digits[permutations as usize].clone()); | ||||||
|  |         digits.remove(permutations as usize); | ||||||
|     } |     } | ||||||
|     Ok(perm) |     Ok(perm) | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct Permutator<T: Clone + Ord> { | pub struct Permutator<T: Clone + Ord> { | ||||||
|     pub current: Vec<T>, |     pub elements: Vec<T>, | ||||||
|     idx: usize, |     idx: usize, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<T: Clone + Ord> Permutator<T> { | impl<T: Clone + Ord> Permutator<T> { | ||||||
|     pub fn new(elements: Vec<T>) -> Self { |     pub fn new(elements: Vec<T>) -> Self { | ||||||
|         Self { |         Self { elements, idx: 0 } | ||||||
|             current: elements, |  | ||||||
|             idx: 0, |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<T: Clone + Ord> Iterator for Permutator<T> { | impl<T: Clone + Ord + std::fmt::Display> Iterator for Permutator<T> { | ||||||
|     type Item = Vec<T>; |     type Item = Vec<T>; | ||||||
|     /// Returns the next permutation and changes the current permutation to it |     /// Returns the next permutation and changes the current permutation to it | ||||||
|     /// This operation wraps around |     /// This operation wraps around | ||||||
|     fn next(&mut self) -> Option<Self::Item> { |     fn next(&mut self) -> Option<Self::Item> { | ||||||
|         if self.current.is_empty() { |         if self.elements.is_empty() { | ||||||
|             return None; |             return None; | ||||||
|         } |         } | ||||||
|         let mut digits = self.current.clone(); |         if self.idx == 0 { | ||||||
|         if self.idx == factorial(digits.len()) { |             self.idx += 1; | ||||||
|  |             return Some(self.elements.clone()); | ||||||
|  |         } | ||||||
|  |         let num_unique_elements = self.elements.len(); | ||||||
|  |         if Number::from(self.idx as isize) == factorial(num_unique_elements) { | ||||||
|             return None; |             return None; | ||||||
|         } |         } | ||||||
|  |         let mut elements = self.elements.clone(); | ||||||
|         let mut perm = Vec::new(); |         let mut perm = Vec::new(); | ||||||
|         let num_unique_digits = digits.len(); |         let mut remainder = Number::from(self.idx as isize); | ||||||
|         let mut remainder = 1; |         for idx in 1..=num_unique_elements { | ||||||
|         for idx in 1..=digits.len() { |             let permutations = remainder.clone() / factorial(num_unique_elements - idx); | ||||||
|             let permutations = remainder / factorial(num_unique_digits - idx); |             remainder %= factorial(num_unique_elements - idx); | ||||||
|             remainder %= factorial(num_unique_digits - idx); |             let permutations: isize = permutations.try_into().unwrap(); | ||||||
|             perm.push(digits[permutations].clone()); |             perm.push(elements.remove(permutations as usize)); | ||||||
|             digits.remove(permutations); |  | ||||||
|         } |         } | ||||||
|         self.idx += 1; |         self.idx += 1; | ||||||
|         self.current = digits; |         Some(perm) | ||||||
|         Some(self.current.clone()) |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod test { | ||||||
|  |     use crate::permutation::{nth_lex, Permutator}; | ||||||
|  |  | ||||||
|  |     const SMALL: [i8; 3] = [1, 2, 3]; | ||||||
|  |  | ||||||
|  |     // Nth Lex | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn nth_lex_zero_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         assert!(nth_lex(small, 0).is_err()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn nth_lex_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 1).unwrap(), vec![1, 2, 3]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 2).unwrap(), vec![1, 3, 2]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 3).unwrap(), vec![2, 1, 3]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 4).unwrap(), vec![2, 3, 1]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 5).unwrap(), vec![3, 1, 2]); | ||||||
|  |         assert_eq!(nth_lex(small.clone(), 6).unwrap(), vec![3, 2, 1]); | ||||||
|  |         assert!(nth_lex(small.clone(), 7).is_err()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Permutator | ||||||
|  |     #[test] | ||||||
|  |     fn perm_small() { | ||||||
|  |         let small = SMALL.to_vec(); | ||||||
|  |         let mut comb = Permutator::new(small); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![1, 2, 3])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![1, 3, 2])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![2, 1, 3])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![2, 3, 1])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![3, 1, 2])); | ||||||
|  |         assert_eq!(comb.next(), Some(vec![3, 2, 1])); | ||||||
|  |         assert_eq!(comb.next(), None); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								src/time.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/time.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | use std::time::Duration; | ||||||
|  |  | ||||||
|  | pub fn get_elapsed_string(duration: Duration) -> String { | ||||||
|  |     let total_microseconds = duration.as_micros(); | ||||||
|  |     let total_milliseconds = duration.as_millis(); | ||||||
|  |     let seconds = duration.as_secs() % 60; | ||||||
|  |     let minutes = (duration.as_secs() / 60) % 60; | ||||||
|  |     let milliseconds = total_milliseconds % 1000; | ||||||
|  |     let microseconds = total_microseconds % 1_000; | ||||||
|  |  | ||||||
|  |     let mut parts = vec![]; | ||||||
|  |  | ||||||
|  |     if minutes > 0 { | ||||||
|  |         parts.push(format!("{}m", minutes)); | ||||||
|  |     } | ||||||
|  |     if seconds > 0 { | ||||||
|  |         parts.push(format!("{}s", seconds)); | ||||||
|  |     } | ||||||
|  |     if milliseconds > 0 { | ||||||
|  |         parts.push(format!("{}ms", milliseconds)); | ||||||
|  |     } | ||||||
|  |     if microseconds > 0 { | ||||||
|  |         parts.push(format!("{}µs", microseconds)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     parts.join(" ") | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user