From cf20e0ff3cad4a5e70b98343bf3e84643083777c Mon Sep 17 00:00:00 2001 From: Pedro Ferreira Date: Thu, 11 Dec 2025 07:52:38 +0000 Subject: [PATCH] fix(quest-10) --- solutions/adding/Cargo.toml | 2 +- solutions/adding/src/lib.rs | 84 +---- solutions/adding_twice/Cargo.toml | 2 +- solutions/adding_twice/src/lib.rs | 120 +------ solutions/closures/Cargo.toml | 2 +- solutions/closures/src/lib.rs | 36 +-- solutions/get_products/Cargo.toml | 2 +- solutions/get_products/src/lib.rs | 79 +---- solutions/highest/Cargo.toml | 2 +- solutions/highest/src/lib.rs | 101 ++---- solutions/iterators/Cargo.toml | 2 +- solutions/iterators/src/lib.rs | 44 ++- solutions/markdown_to_html/Cargo.toml | 2 + solutions/markdown_to_html/src/lib.rs | 168 +++++----- solutions/project_motion/Cargo.toml | 2 +- solutions/project_motion/src/lib.rs | 301 ++---------------- solutions/roman_numbers_iter/Cargo.toml | 2 +- solutions/roman_numbers_iter/src/lib.rs | 207 +++++------- solutions/sales/Cargo.toml | 2 +- solutions/sales/src/lib.rs | 255 +++------------ solutions/slices_to_map/Cargo.toml | 2 +- solutions/slices_to_map/src/lib.rs | 77 +---- solutions/step_iterator/Cargo.toml | 2 +- solutions/step_iterator/src/lib.rs | 93 +----- tests/adding_test/Cargo.toml | 2 +- tests/adding_test/src/{main.rs => lib.rs} | 23 +- tests/adding_twice_test/Cargo.toml | 2 +- .../adding_twice_test/src/{main.rs => lib.rs} | 38 +-- tests/closures_test/Cargo.toml | 2 +- tests/closures_test/src/lib.rs | 17 + tests/closures_test/src/main.rs | 28 -- tests/get_products_test/Cargo.toml | 2 +- tests/get_products_test/src/lib.rs | 20 ++ tests/get_products_test/src/main.rs | 49 --- tests/highest_test/Cargo.toml | 2 +- tests/highest_test/src/lib.rs | 42 +++ tests/highest_test/src/main.rs | 80 ----- tests/iterators_test/Cargo.toml | 2 +- tests/iterators_test/src/lib.rs | 46 +++ tests/iterators_test/src/main.rs | 54 ---- tests/markdown_to_html_test/Cargo.toml | 3 +- tests/markdown_to_html_test/src/lib.rs | 37 +++ tests/markdown_to_html_test/src/main.rs | 89 ------ .../src/tests/blockquotes.html | 2 + .../src/tests/blockquotes.md | 2 + .../src/tests/bold_italic.html | 2 + .../src/tests/bold_italic.md | 2 + .../src/tests/example.html | 14 + .../src/tests/example.md | 24 ++ .../src/tests/titles.html | 5 + .../markdown_to_html_test/src/tests/titles.md | 6 + tests/project_motion_test/Cargo.toml | 3 +- tests/project_motion_test/src/lib.rs | 92 ++++++ tests/project_motion_test/src/main.rs | 143 --------- tests/roman_numbers_iter_test/Cargo.toml | 2 +- tests/roman_numbers_iter_test/src/lib.rs | 16 + tests/roman_numbers_iter_test/src/main.rs | 100 ------ tests/sales_test/Cargo.toml | 2 +- tests/sales_test/src/lib.rs | 119 +++++++ tests/sales_test/src/main.rs | 133 -------- tests/slices_to_map_test/Cargo.toml | 2 +- tests/slices_to_map_test/src/lib.rs | 52 +++ tests/slices_to_map_test/src/main.rs | 78 ----- tests/step_iterator_test/Cargo.toml | 2 +- tests/step_iterator_test/src/lib.rs | 32 ++ tests/step_iterator_test/src/main.rs | 83 ----- 66 files changed, 872 insertions(+), 2171 deletions(-) rename tests/adding_test/src/{main.rs => lib.rs} (77%) rename tests/adding_twice_test/src/{main.rs => lib.rs} (61%) create mode 100644 tests/closures_test/src/lib.rs delete mode 100644 tests/closures_test/src/main.rs create mode 100644 tests/get_products_test/src/lib.rs delete mode 100644 tests/get_products_test/src/main.rs create mode 100644 tests/highest_test/src/lib.rs delete mode 100644 tests/highest_test/src/main.rs create mode 100644 tests/iterators_test/src/lib.rs delete mode 100644 tests/iterators_test/src/main.rs create mode 100644 tests/markdown_to_html_test/src/lib.rs delete mode 100644 tests/markdown_to_html_test/src/main.rs create mode 100644 tests/markdown_to_html_test/src/tests/blockquotes.html create mode 100644 tests/markdown_to_html_test/src/tests/blockquotes.md create mode 100644 tests/markdown_to_html_test/src/tests/bold_italic.html create mode 100644 tests/markdown_to_html_test/src/tests/bold_italic.md create mode 100644 tests/markdown_to_html_test/src/tests/example.html create mode 100644 tests/markdown_to_html_test/src/tests/example.md create mode 100644 tests/markdown_to_html_test/src/tests/titles.html create mode 100644 tests/markdown_to_html_test/src/tests/titles.md create mode 100644 tests/project_motion_test/src/lib.rs delete mode 100644 tests/project_motion_test/src/main.rs create mode 100644 tests/roman_numbers_iter_test/src/lib.rs delete mode 100644 tests/roman_numbers_iter_test/src/main.rs create mode 100644 tests/sales_test/src/lib.rs delete mode 100644 tests/sales_test/src/main.rs create mode 100644 tests/slices_to_map_test/src/lib.rs delete mode 100644 tests/slices_to_map_test/src/main.rs create mode 100644 tests/step_iterator_test/src/lib.rs delete mode 100644 tests/step_iterator_test/src/main.rs diff --git a/solutions/adding/Cargo.toml b/solutions/adding/Cargo.toml index f68aa461..0ba9af7a 100644 --- a/solutions/adding/Cargo.toml +++ b/solutions/adding/Cargo.toml @@ -2,7 +2,7 @@ name = "adding" version = "0.1.0" authors = ["MSilva95 "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/adding/src/lib.rs b/solutions/adding/src/lib.rs index 3d879514..111e48ae 100644 --- a/solutions/adding/src/lib.rs +++ b/solutions/adding/src/lib.rs @@ -1,83 +1,3 @@ -/* -## adding - -### Instructions - -Create the function `add_curry` that returns a closure. -The purpose is to curry the add method to create more variations -so that you can use the curried method like: - -// let add_1 = add_curry(1); -// add_1(2) -> 3 - - ### Notions - -- https://doc.rust-lang.org/book/ch13-02-iterators.html - -fn main() { - let add10 = add_curry(-10); - let add20 = add_curry(2066); - let add30 = add_curry(300000); - - println!("{}", add10(5)); - println!("{}", add20(195)); - println!("{}", add30(5696)); -} -*/ -pub fn add_curry(x: i32) -> impl Fn(i32) -> i32 { - return move |y| x + y; -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_zero() { - let z = add_curry(0); - assert_eq!(z(1999), 1999); - } - - #[test] - fn test_negatives() { - let neg = add_curry(-10); - assert_eq!(neg(6), -4); - assert_eq!(neg(10), 0); - assert_eq!(neg(600), 590); - assert_eq!(neg(1000), 990); - assert_eq!(neg(463), 453); - assert_eq!(neg(400000000), 399999990); - } - - #[test] - fn test_add10() { - let add10 = add_curry(10); - assert_eq!(add10(6), 16); - assert_eq!(add10(10), 20); - assert_eq!(add10(600), 610); - assert_eq!(add10(1000), 1010); - assert_eq!(add10(463), 473); - assert_eq!(add10(400000000), 400000010); - } - - #[test] - fn test_add250() { - let add250 = add_curry(250); - assert_eq!(add250(6), 256); - assert_eq!(add250(10), 260); - assert_eq!(add250(600), 850); - assert_eq!(add250(1000), 1250); - assert_eq!(add250(463), 713); - assert_eq!(add250(400000000), 400000250); - } - #[test] - fn test_add3960() { - let add3960 = add_curry(3960); - assert_eq!(add3960(6), 3966); - assert_eq!(add3960(10), 3970); - assert_eq!(add3960(600), 4560); - assert_eq!(add3960(1000), 4960); - assert_eq!(add3960(463), 4423); - assert_eq!(add3960(400000000), 400003960); - } +pub const fn add_curry(x: i32) -> impl Fn(i32) -> i32 { + move |y| x + y } diff --git a/solutions/adding_twice/Cargo.toml b/solutions/adding_twice/Cargo.toml index 67ae9b3e..a3dbc513 100644 --- a/solutions/adding_twice/Cargo.toml +++ b/solutions/adding_twice/Cargo.toml @@ -2,7 +2,7 @@ name = "adding_twice" version = "0.1.0" authors = ["MSilva95 "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/adding_twice/src/lib.rs b/solutions/adding_twice/src/lib.rs index 924cb2b0..c4de6933 100644 --- a/solutions/adding_twice/src/lib.rs +++ b/solutions/adding_twice/src/lib.rs @@ -1,119 +1,7 @@ -/* -## adding_twice - -### Instructions - -In this exercise you will have to reuse your `add_curry` function -Then you have to complete the function `twice` using closures, this function will -take a function f(x) as parameter and return a function f(f(x)) -So, the purpose of this function is to add two times the value in `add_curry` to the original value. - -### Notions - -- https://doc.rust-lang.org/rust-by-example/fn/hof.html#higher-order-functions - -### Expected functions - -The type of the arguments are missing use the example `main` function to determine the correct type. - -```rust -fn twice(F: _) -> _{} -``` - -### Usage - -Here is a program to test your function. - -```rust -fn main() { - let add10 = add_curry(10); - let value = twice(add10); - println!("The value is {}", value(7)); - - let add20 = add_curry(20); - let value = twice(add20); - println!("The value is {}", value(7)); - - let add30 = add_curry(30); - let value = twice(add30); - println!("The value is {}", value(7)); - - let neg = add_curry(-32); - let value = twice(neg); - println!("The value is {}", value(7)); -} -``` - -And its output - -```console -student@ubuntu:~/[[ROOT]]/test$ cargo run -The value is 27 -The value is 47 -The value is 67 -The value is -57 -student@ubuntu:~/[[ROOT]]/test$ -``` - -*/ - -pub fn twice(function: impl Fn(T) -> T) -> impl Fn(T) -> T { - move |a| function(function(a)) +pub const fn add_curry(x: i32) -> impl Fn(i32) -> i32 { + move |y| x + y } -pub fn add_curry(x: i32) -> impl Fn(i32) -> i32 { - return move |y| -> i32 { x + y }; -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_zero_twice() { - let z = twice(add_curry(0)); - assert_eq!(z(1902), 1902); - } - - #[test] - fn test_negative_twice() { - let neg = twice(add_curry(-32)); - assert_eq!(neg(6), -58); - assert_eq!(neg(10), -54); - assert_eq!(neg(660), 596); - assert_eq!(neg(1902), 1838); - assert_eq!(neg(463), 399); - assert_eq!(neg(400000000), 399999936); - } - - #[test] - fn test_add10_twice() { - let value = twice(add_curry(10)); - assert_eq!(value(6), 26); - assert_eq!(value(10), 30); - assert_eq!(value(600), 620); - assert_eq!(value(1000), 1020); - assert_eq!(value(463), 483); - assert_eq!(value(400000000), 400000020); - } - #[test] - fn test_add20_twice() { - let value = twice(add_curry(20)); - assert_eq!(value(6), 46); - assert_eq!(value(10), 50); - assert_eq!(value(600), 640); - assert_eq!(value(1000), 1040); - assert_eq!(value(463), 503); - assert_eq!(value(400000000), 400000040); - } - #[test] - fn test_add30_twice() { - let value = twice(add_curry(30)); - assert_eq!(value(6), 66); - assert_eq!(value(10), 70); - assert_eq!(value(600), 660); - assert_eq!(value(1000), 1060); - assert_eq!(value(463), 523); - assert_eq!(value(400000000), 400000060); - } +pub const fn twice(f: impl Fn(i32) -> i32) -> impl Fn(i32) -> i32 { + move |x| f(f(x)) } diff --git a/solutions/closures/Cargo.toml b/solutions/closures/Cargo.toml index 52aabe34..dfc459ae 100644 --- a/solutions/closures/Cargo.toml +++ b/solutions/closures/Cargo.toml @@ -2,7 +2,7 @@ name = "closures" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/closures/src/lib.rs b/solutions/closures/src/lib.rs index 2b8a17f6..fae3734a 100644 --- a/solutions/closures/src/lib.rs +++ b/solutions/closures/src/lib.rs @@ -1,32 +1,8 @@ -// Using closures and iterators create a function, -// first_fifty_even_square() that returns the -// first 50 pair numbers squares that it's [4, 16, 36, ..., 10000]. - -use std::iter::Iterator; - +#[inline] pub fn first_fifty_even_square() -> Vec { - (1..101).filter(|x| x % 2 == 0).map(|x| x * x).collect() -} - -// fn main() { -// println!("Hello, world!"); -// let v1 = first_fifty_even_square(); - -// println!("All elements in {:?}, len = {}", v1, v1.len()); -// } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test() { - let v1 = vec![ - 4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576, 676, 784, 900, 1024, 1156, 1296, - 1444, 1600, 1764, 1936, 2116, 2304, 2500, 2704, 2916, 3136, 3364, 3600, 3844, 4096, - 4356, 4624, 4900, 5184, 5476, 5776, 6084, 6400, 6724, 7056, 7396, 7744, 8100, 8464, - 8836, 9216, 9604, 10000, - ]; - assert_eq!(v1, first_fifty_even_square()); - } + (1..) + .filter(|x| x % 2 == 0) + .take(50) + .map(|x| x * x) + .collect() } diff --git a/solutions/get_products/Cargo.toml b/solutions/get_products/Cargo.toml index daf536ba..7d4ac1ab 100644 --- a/solutions/get_products/Cargo.toml +++ b/solutions/get_products/Cargo.toml @@ -2,7 +2,7 @@ name = "get_products" version = "0.1.0" authors = ["MSilva95 "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/get_products/src/lib.rs b/solutions/get_products/src/lib.rs index 5c396354..a59ae235 100644 --- a/solutions/get_products/src/lib.rs +++ b/solutions/get_products/src/lib.rs @@ -1,71 +1,10 @@ -/* -## get_products - -### Instructions - -Create a function `get_products` that takes an array of integers, and returns an array of the products -of each index. For this exercise to be correct you will have to return the product of every index -except the current one. - -### Example: - -Input: arr[] = {10, 3, 5, 6, 2} -Output: prod[] = {180, 600, 360, 300, 900} - -```rust -fn main() { - let arr: Vec = vec![1, 7, 3, 4]; - let output = get_products(arr); - println!("{:?}", output); -} -``` -*/ - -pub fn get_products(arr: Vec) -> Vec { - let mut counter: usize = 0; - let mut product_results: Vec = Vec::new(); - - if arr.len() < 2 { - return product_results; - }; - - for _ in arr.iter() { - let mut prod: usize = 1; - let mut others: Vec = arr.clone(); - others.remove(counter); - for x in others.iter() { - prod *= *x; - } - product_results.push(prod); - counter += 1; - } - return product_results; -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn test_multiple() { - let arr: Vec = vec![1, 7, 3, 4]; - let output = get_products(arr); - let arr2: Vec = vec![10, 3, 5, 6, 2]; - let output2 = get_products(arr2); - assert_eq!(output, vec![84, 12, 28, 21]); - assert_eq!(output2, vec![180, 600, 360, 300, 900]); - } - - #[test] - fn test_empty_case() { - let arr: Vec = Vec::new(); - let output = get_products(arr); - assert_eq!(output, vec![]); - } - - #[test] - fn test_single_case() { - let arr: Vec = vec![2]; - let output = get_products(arr); - assert_eq!(output, vec![]); - } +#[inline] +pub fn get_products(arr: [u32; N]) -> [u32; N] { + std::array::from_fn(|i| { + arr.into_iter() + .enumerate() + .filter(|&(j, _)| j != i) + .map(|(_, v)| v) + .product() + }) } diff --git a/solutions/highest/Cargo.toml b/solutions/highest/Cargo.toml index 4ec8d881..a973bc4b 100644 --- a/solutions/highest/Cargo.toml +++ b/solutions/highest/Cargo.toml @@ -2,7 +2,7 @@ name = "highest" version = "0.1.0" authors = ["MSilva95 "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/highest/src/lib.rs b/solutions/highest/src/lib.rs index 41c8e427..abb3cc2b 100644 --- a/solutions/highest/src/lib.rs +++ b/solutions/highest/src/lib.rs @@ -1,98 +1,35 @@ -/* -## highest - -### Instructions - - In this exercise you will be given a `Numbers` struct. - Your task is to write these methods: - `list` that returns an `array` with every number in the struct - `latest` thar returns an `Option` with the last added number - `highest` that return an `Option` with the highest number from the list, - `highest_three` that returns a `Vec` with the three highest numbers. - - ### Notions - -- https://doc.rust-lang.org/book/ch13-02-iterators.html - -fn main() { - let expected = [30, 500, 20, 70]; - let n = Numbers::new(&expected); - println!("{:?}", n.list()); - println!("{:?}", n.highest()); - println!("{:?}", n.latest()); - println!("{:?}", n.highest_three()); -} -*/ - #[derive(Debug)] -pub struct Numbers<'a> { - numbers: &'a [u32], +pub struct Numbers { + numbers: [u32; N], } -impl<'a> Numbers<'a> { - pub fn new(numbers: &'a [u32]) -> Self { - Numbers { numbers } +impl Numbers { + pub const fn new(numbers: [u32; N]) -> Self { + Self { numbers } } - pub fn list(&self) -> &[u32] { - self.numbers + pub const fn inner(&self) -> &[u32] { + self.numbers.as_slice() } - pub fn latest(&self) -> Option { - self.numbers.iter().last().map(|u| *u) + pub const fn latest(&self) -> Option { + self.numbers.last().copied() } + #[inline] pub fn highest(&self) -> Option { - self.numbers.iter().max().map(|u| *u) + self.numbers.iter().max().copied() } - pub fn highest_three(&self) -> Vec { - let mut ordered_numbers = self.numbers.clone().to_owned(); - ordered_numbers.sort_by(|a, b| b.cmp(a)); - ordered_numbers.iter().take(3).map(|u| *u).collect() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_List() { - let expected = [30, 50, 20, 70]; - let n = Numbers::new(&expected); - assert_eq!(n.list(), &expected); - } + #[inline] + pub fn highest_three(&self) -> Option<[u32; 3]> { + if self.numbers.len() < 3 { + return None; + } - #[test] - fn test_Latest() { - let n = Numbers::new(&[100, 0, 90, 30]); - let f = Numbers::new(&[]); - assert_eq!(n.latest(), Some(30)); - assert_eq!(f.latest(), None); - } - - #[test] - fn test_Highest() { - let n = Numbers::new(&[40, 100, 70]); - let f = Numbers::new(&[]); - assert_eq!(n.highest(), Some(100)); - assert_eq!(f.highest(), None); - } + let mut ord = self.numbers; + ord.sort_unstable_by(|a, b| b.cmp(a)); - #[test] - fn test_Highest_Three() { - let e = Numbers::new(&[10, 30, 90, 30, 100, 20, 10, 0, 30, 40, 40, 70, 70]); - let f = Numbers::new(&[40, 20, 40, 30]); - let g = Numbers::new(&[30, 70]); - let h = Numbers::new(&[40]); - let i = Numbers::new(&[]); - let j = Numbers::new(&[20, 10, 30]); - assert_eq!(e.highest_three(), vec![100, 90, 70]); - assert_eq!(f.highest_three(), vec![40, 40, 30]); - assert_eq!(g.highest_three(), vec![70, 30]); - assert_eq!(h.highest_three(), vec![40]); - assert!(i.highest_three().is_empty()); - assert_eq!(j.highest_three(), vec![30, 20, 10]); + Some([ord[0], ord[1], ord[2]]) } } diff --git a/solutions/iterators/Cargo.toml b/solutions/iterators/Cargo.toml index d2259c61..e14c0f22 100644 --- a/solutions/iterators/Cargo.toml +++ b/solutions/iterators/Cargo.toml @@ -2,7 +2,7 @@ name = "iterators" version = "0.1.0" authors = ["MSilva95 "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/iterators/src/lib.rs b/solutions/iterators/src/lib.rs index 79d53f91..a0a776e5 100644 --- a/solutions/iterators/src/lib.rs +++ b/solutions/iterators/src/lib.rs @@ -1,33 +1,25 @@ -#[derive(Copy, Clone)] -pub struct Collatz { - pub v: u64, -} +use std::iter::successors; -impl Collatz { - pub fn new(aux: u64) -> Self { - Collatz { v: aux } +pub fn collatz(n: u64) -> Option { + if n == 0 { + return None; } -} - -impl Iterator for Collatz { - type Item = Collatz; - fn next(&mut self) -> Option { - if self.v <= 1 { - None - } else { - let old_value = self.v; - if self.v % 2 == 0 { - self.v /= 2; + let mut seq = successors(Some(Ok(n)), |&val| { + val.ok().and_then(|x| { + if x == 1 { + None } else { - self.v = self.v * 3 + 1; + Some(match x % 2 { + 0 => Ok(x / 2), + 1 => x.checked_mul(3).and_then(|y| y.checked_add(1)).ok_or(()), + _ => unreachable!(), + }) } - Some(Collatz { v: old_value }) - } - } -} + }) + }); -pub fn collatz(n: u64) -> usize { - let nb = Collatz::new(n); - nb.count() + seq.try_fold(0, |count, step| step.map(|_| count + 1)) + .ok() + .map(|count| count - 1) } diff --git a/solutions/markdown_to_html/Cargo.toml b/solutions/markdown_to_html/Cargo.toml index 7fafbddc..ce737e71 100644 --- a/solutions/markdown_to_html/Cargo.toml +++ b/solutions/markdown_to_html/Cargo.toml @@ -6,3 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +const_format = "0.2.35" +itertools = "0.14.0" diff --git a/solutions/markdown_to_html/src/lib.rs b/solutions/markdown_to_html/src/lib.rs index 83096b6c..040743d1 100644 --- a/solutions/markdown_to_html/src/lib.rs +++ b/solutions/markdown_to_html/src/lib.rs @@ -1,100 +1,92 @@ -#[derive(Debug)] -struct Token { - start: &'static str, - end: &'static str, - r_start: &'static str, - r_end: &'static str, - can_be_nested: bool, -} +#![feature(string_replace_in_place)] -const TOKENS: [Token; 6] = [ - Token { - start: "# ", - end: "\n", - r_start: "

", - r_end: "

\n", - can_be_nested: false, - }, - Token { - start: "## ", - end: "\n", - r_start: "

", - r_end: "

\n", - can_be_nested: false, - }, - Token { - start: "### ", - end: "\n", - r_start: "

", - r_end: "

\n", - can_be_nested: false, - }, - Token { - start: "> ", - end: "\n", - r_start: "
", - r_end: "
\n", - can_be_nested: true, - }, - Token { - start: "**", - end: "**", - r_start: "", - r_end: "", - can_be_nested: true, - }, - Token { - start: "*", - end: "*", - r_start: "", - r_end: "", - can_be_nested: true, - }, -]; +use std::sync::LazyLock; -pub fn markdown_to_html(s: &str) -> String { - convert(s, true) -} +use itertools::Itertools; -pub fn convert(s: &str, is_root: bool) -> String { - let mut html = String::new(); +const START_DELIM: (&str, &str) = ("<", ">"); +const END_DELIM: (&str, &str) = (""); +const INLINE_DELIM: (&str, &str) = ("<", " />"); - let mut i = 0; - while i < s.len() { - match get_token(&s[i..], is_root) { - Some(t) => { - i += t.start.len(); - html += t.r_start; +static HEADINGS: LazyLock<[(&str, (String, String)); 3]> = LazyLock::new(|| { + [("# ", "h1"), ("## ", "h2"), ("### ", "h3")].map(|(from, to)| (from, as_element(to))) +}); +static BLOCKQUOTE: LazyLock<(&str, (String, String))> = + LazyLock::new(|| ("> ", as_element("blockquote"))); +static BOLD: LazyLock<(&str, (String, String))> = LazyLock::new(|| ("**", as_element("strong"))); +static ITALIC: LazyLock<(&str, (String, String))> = LazyLock::new(|| ("*", as_element("em"))); +static SEPARATOR: LazyLock<(&str, String)> = LazyLock::new(|| { + ( + "****", + format!("{}{}{}", INLINE_DELIM.0, "hr", INLINE_DELIM.1), + ) +}); - let content_len = get_content_len(t, &s[i..]); - html += &convert(&s[i..i + content_len], false); +#[inline] +fn as_element(to: &str) -> (String, String) { + ( + format!("{}{}{}", START_DELIM.0, to, START_DELIM.1), + format!("{}{}{}", END_DELIM.0, to, END_DELIM.1), + ) +} + +#[inline] +pub fn markdown_to_html(s: &str) -> String { + s.lines() + .map(|l| l.trim_ascii()) + .filter(|l| !l.is_empty()) + .peekable() + .batching(|it| { + let is_block = |l: &str| { + l.starts_with(SEPARATOR.0) + || l.starts_with(BLOCKQUOTE.0) + || HEADINGS.iter().any(|&(h, _)| l.starts_with(h)) + }; - html += t.r_end; - i += content_len + t.end.len(); + let line = it.next()?; + + if is_block(line) { + return Some(line.to_owned()); } - None => { - html.push(s.chars().nth(i).unwrap()); - i += 1; + + Some( + std::iter::once(line) + .chain(std::iter::from_fn(|| { + it.next_if(|l| !is_block(l) && !l.is_empty()) + .map(|s| s.trim_ascii_end()) + })) + .join("\n"), + ) + }) + .map(|mut chunk| { + let replace = |chunk: &mut String, &(from, ref to): &(&str, (String, String))| { + chunk.push_str(&to.1); + chunk.replace_first(from, &to.0); + }; + + if chunk.starts_with(SEPARATOR.0) { + chunk.replace_first(SEPARATOR.0, &SEPARATOR.1); + } else if chunk.starts_with(BLOCKQUOTE.0) { + replace(&mut chunk, &BLOCKQUOTE); + } else if let Some(v) = HEADINGS.iter().find(|&&(h, _)| chunk.starts_with(h)) { + replace(&mut chunk, v); } - } - } - html -} -fn get_token(s: &str, is_root: bool) -> Option<&'static Token> { - TOKENS - .iter() - .find(|t| (is_root || t.can_be_nested) && s.starts_with(t.start)) -} + chunk + }) + .map(|mut chunk| { + let mut replace = |&(from, ref to): &(&str, (String, String))| { + let mut toggle = false; + while chunk.contains(from) { + toggle = !toggle; + chunk.replace_first(from, if toggle { &to.0 } else { &to.1 }); + } + }; -fn get_content_len(t: &Token, s: &str) -> usize { - let mut len = 0; - while len < s.len() { - if s[len..].starts_with(t.end) { - break; - } - len += 1; - } + replace(&BOLD); + replace(&ITALIC); - len + chunk + }) + .join("\n") } diff --git a/solutions/project_motion/Cargo.toml b/solutions/project_motion/Cargo.toml index 00cf912b..30983d7a 100644 --- a/solutions/project_motion/Cargo.toml +++ b/solutions/project_motion/Cargo.toml @@ -2,7 +2,7 @@ name = "project_motion" version = "0.1.0" authors = ["lee "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/project_motion/src/lib.rs b/solutions/project_motion/src/lib.rs index 125d0df5..5469afcb 100644 --- a/solutions/project_motion/src/lib.rs +++ b/solutions/project_motion/src/lib.rs @@ -1,287 +1,50 @@ -/* -## project_motion - -### Instructions - -For this exercise, you will have to create a [projectile motion](https://cimg2.ck12.org/datastreams/f-d%3Abb024be6673110b31e78b46819e792adaed8dc661e082a61f0a6d64e%2BIMAGE%2BIMAGE.1). - -Two structures will be provided. A structure called `Object` which will have the corresponding values of X and Y. - -A structure called `ThrowObject` that will contain all the variables that are -essential for the projectile physics (initial position, initial velocity, current position, current velocity and time). - -You must implement : - -- A function `new` that will initialize the ThrowObject with a given initial position and an initial velocity. -- The trait Iterator with the `.next()` in which the position and speed of the object must be calculated after 1 second. - It will return an `Option` with the ThrowObject, or it will return `None` if the ThrowObject has already reached the floor. - -### Notions - -- [trait Iterator](https://doc.rust-lang.org/std/iter/trait.Iterator.html) -- [iter](https://doc.rust-lang.org/rust-by-example/trait/iter.html) - -*/ - -#[derive(Debug, Clone, PartialEq)] -pub struct Object { - pub x: f32, - pub y: f32, +#[derive(Debug, PartialEq, Clone, Copy)] +pub struct Vec2 { + pub x: f64, + pub y: f64, } -#[derive(Debug, Clone, PartialEq)] -pub struct ThrowObject { - pub init_position: Object, - pub init_velocity: Object, - pub actual_position: Object, - pub actual_velocity: Object, - pub time: f32, +#[derive(Debug, PartialEq, Clone, Copy)] +pub struct ThrownObject { + initial_position: Vec2, + initial_velocity: Vec2, + elapsed: f64, } -impl ThrowObject { - pub fn new(init_position: Object, init_velocity: Object) -> ThrowObject { - ThrowObject { - init_position: init_position.clone(), - init_velocity: init_velocity.clone(), - actual_position: init_position.clone(), - actual_velocity: init_velocity.clone(), - time: 0.0, +const ACCELERATION: f64 = -9.8; + +impl ThrownObject { + pub const fn new(position: Vec2, velocity: Vec2) -> Self { + Self { + initial_position: position, + initial_velocity: velocity, + elapsed: 0., } } } -impl Iterator for ThrowObject { - type Item = ThrowObject; +impl Iterator for ThrownObject { + type Item = (Vec2, Vec2); - fn next(&mut self) -> Option { - self.time += 1.0; - let actual_distance = Object { - x: round_two(self.init_position.x + self.init_velocity.x * self.time), - y: round_two( - self.init_position.y + self.init_velocity.y * self.time - - 9.8 * self.time * self.time / 2.0, - ), + fn next(&mut self) -> Option<(Vec2, Vec2)> { + self.elapsed += 1.; + + let t = self.elapsed; + + let pos = Vec2 { + x: self.initial_position.x + self.initial_velocity.x * t, + y: self.initial_position.y + self.initial_velocity.y * t + 0.5 * ACCELERATION * t * t, }; - let actual_velocity = Object { - x: round_two(self.init_velocity.x), - y: round_two(self.init_velocity.y - 9.8 * self.time), + let vel = Vec2 { + x: self.initial_velocity.x, + y: self.initial_velocity.y + ACCELERATION * t, }; - if actual_distance.y < 0.0 { + if pos.y <= 0.0 { return None; - } else { - return Some(ThrowObject { - init_position: self.init_position.clone(), - init_velocity: self.init_velocity.clone(), - actual_position: actual_distance, - actual_velocity: actual_velocity, - time: self.time, - }); } - } -} - -fn round_two(nbr: f32) -> f32 { - (nbr * 100.0).round() / 100.0 -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_without_velocity() { - let mut obj = ThrowObject::new(Object { x: 50.0, y: 50.0 }, Object { x: 0.0, y: 0.0 }); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 50.0, y: 50.0 }, - init_velocity: Object { x: 0.0, y: 0.0 }, - actual_position: Object { x: 50.0, y: 45.1 }, - actual_velocity: Object { x: 0.0, y: -9.8 }, - time: 1.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 50.0, y: 50.0 }, - init_velocity: Object { x: 0.0, y: 0.0 }, - actual_position: Object { x: 50.0, y: 30.4 }, - actual_velocity: Object { x: 0.0, y: -19.6 }, - time: 2.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 50.0, y: 50.0 }, - init_velocity: Object { x: 0.0, y: 0.0 }, - actual_position: Object { x: 50.0, y: 5.9 }, - actual_velocity: Object { x: 0.0, y: -29.4 }, - time: 3.0, - }) - ); - - assert!(obj.next().is_none(), "{:?} instead of None", obj); - - assert!(obj.next().is_none(), "{:?} instead of None", obj); - } - - #[test] - fn test_with_velocity() { - let mut obj = ThrowObject::new(Object { x: 0.0, y: 50.0 }, Object { x: 10.0, y: 10.0 }); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 50.0 }, - init_velocity: Object { x: 10.0, y: 10.0 }, - actual_position: Object { x: 10.0, y: 55.1 }, - actual_velocity: Object { x: 10.0, y: 0.2 }, - time: 1.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 50.0 }, - init_velocity: Object { x: 10.0, y: 10.0 }, - actual_position: Object { x: 20.0, y: 50.4 }, - actual_velocity: Object { x: 10.0, y: -9.6 }, - time: 2.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 50.0 }, - init_velocity: Object { x: 10.0, y: 10.0 }, - actual_position: Object { x: 30.0, y: 35.9 }, - actual_velocity: Object { x: 10.0, y: -19.4 }, - time: 3.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 50.0 }, - init_velocity: Object { x: 10.0, y: 10.0 }, - actual_position: Object { x: 40.0, y: 11.6 }, - actual_velocity: Object { x: 10.0, y: -29.2 }, - time: 4.0, - }) - ); - - assert!(obj.next().is_none(), "{:?} instead of None", obj); - } - - #[test] - fn test_with_negative_velocity() { - let mut obj = ThrowObject::new(Object { x: -10.0, y: 50.0 }, Object { x: -10.0, y: -10.0 }); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: -10.0, y: 50.0 }, - init_velocity: Object { x: -10.0, y: -10.0 }, - actual_position: Object { x: -20.0, y: 35.1 }, - actual_velocity: Object { x: -10.0, y: -19.8 }, - time: 1.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: -10.0, y: 50.0 }, - init_velocity: Object { x: -10.0, y: -10.0 }, - actual_position: Object { x: -30.0, y: 10.4 }, - actual_velocity: Object { x: -10.0, y: -29.6 }, - time: 2.0, - }) - ); - - assert!(obj.next().is_none(), "{:?} instead of None", obj); - } - - #[test] - fn test_Long_distance() { - let mut obj = ThrowObject::new(Object { x: 0.0, y: 150.0 }, Object { x: 0.0, y: 10.0 }); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 150.0 }, - init_velocity: Object { x: 0.0, y: 10.0 }, - actual_position: Object { x: 0.0, y: 155.1 }, - actual_velocity: Object { x: 0.0, y: 0.2 }, - time: 1.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 150.0 }, - init_velocity: Object { x: 0.0, y: 10.0 }, - actual_position: Object { x: 0.0, y: 150.4 }, - actual_velocity: Object { x: 0.0, y: -9.6 }, - time: 2.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 150.0 }, - init_velocity: Object { x: 0.0, y: 10.0 }, - actual_position: Object { x: 0.0, y: 135.9 }, - actual_velocity: Object { x: 0.0, y: -19.4 }, - time: 3.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 150.0 }, - init_velocity: Object { x: 0.0, y: 10.0 }, - actual_position: Object { x: 0.0, y: 111.6 }, - actual_velocity: Object { x: 0.0, y: -29.2 }, - time: 4.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 150.0 }, - init_velocity: Object { x: 0.0, y: 10.0 }, - actual_position: Object { x: 0.0, y: 77.5 }, - actual_velocity: Object { x: 0.0, y: -39.0 }, - time: 5.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 150.0 }, - init_velocity: Object { x: 0.0, y: 10.0 }, - actual_position: Object { x: 0.0, y: 33.6 }, - actual_velocity: Object { x: 0.0, y: -48.8 }, - time: 6.0, - }) - ); - assert!(obj.next().is_none(), "{:?} instead of None", obj); + Some((pos, vel)) } } diff --git a/solutions/roman_numbers_iter/Cargo.toml b/solutions/roman_numbers_iter/Cargo.toml index c8cdc9d0..5e9e723f 100644 --- a/solutions/roman_numbers_iter/Cargo.toml +++ b/solutions/roman_numbers_iter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "roman_numbers_iter" version = "0.1.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/roman_numbers_iter/src/lib.rs b/solutions/roman_numbers_iter/src/lib.rs index d708f04f..c14176f8 100644 --- a/solutions/roman_numbers_iter/src/lib.rs +++ b/solutions/roman_numbers_iter/src/lib.rs @@ -1,159 +1,112 @@ -// ## roman_numbers_iter - -// ### Instructions - -// Implement the `Iterator` trait for the `RomanNumber` type. You should use the code from the previous exercise roman_numbers. - -// ### Notions - -// - [Trait Iterator](https://doc.rust-lang.org/std/iter/trait.Iterator.html) - -// ### Expected Functions - -// ```rust -// //... - -// impl Iterator for RomanNumber {} -// ``` - -// ### Usage - -// Here is a program to test your function. - -// ```rust -// use roman_numbers::RomanNumber; - -// fn main() { -// let mut number = RomanNumber::from(15); - -// println!("{:?}", number); -// println!("{:?}", number.next()); -// } -// ``` - -// And its output - -// ```console -// $ cargo run -// RomanNumber([X, V]) -// Some(RomanNumber([X, V, I])) -// $ -// ``` - -use crate::RomanDigit::*; +use std::iter; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum RomanDigit { - Nulla, - I, - V, - X, - L, - C, - D, - M, + Nulla = 0, + I = 1, + V = 5, + X = 10, + L = 50, + C = 100, + D = 500, + M = 1000, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct RomanNumber(pub Vec); -impl From for RomanDigit { - fn from(n: u32) -> Self { - match n { - 1..=4 => I, - 5..=9 => V, - 10..=49 => X, - 50..=99 => L, - 100..=499 => C, - 500..=999 => D, - 1000..=5000 => M, - _ => Nulla, +impl RomanDigit { + const fn base(value: u32) -> Self { + use RomanDigit::*; + + if value >= M as u32 { + M + } else if value >= D as u32 { + D + } else if value >= C as u32 { + C + } else if value >= L as u32 { + L + } else if value >= X as u32 { + X + } else if value >= V as u32 { + V + } else if value >= I as u32 { + I + } else { + Nulla } } -} -impl From for u32 { - fn from(n: RomanDigit) -> Self { - match n { - I => 1, - V => 5, - X => 10, - L => 50, - C => 100, - D => 500, - M => 1000, - _ => 0, - } + fn take(value: &mut u32) -> Vec { + let digits = value.checked_ilog10().unwrap_or_default() + 1; + + let d = *value / 10u32.pow(digits - 1); + + let ret = if (d + 1) % 5 == 0 { + let v = Self::base(((d + 1) / 5) * 10u32.pow(digits - 1)); + *value -= d * 10u32.pow(digits - 1); + vec![v, Self::base((d + 1) * 10u32.pow(digits - 1))] + } else { + let v = Self::base(*value); + *value -= v as u32; + vec![v] + }; + + ret } } impl From for RomanNumber { - fn from(n: u32) -> Self { - if n == 0 { - return RomanNumber(vec![Nulla]); + fn from(value: u32) -> Self { + if value == 0 { + return Self(vec![RomanDigit::Nulla]); } - let mut quotient = n; - let mut p = 0; - let mut reverse_roman = Vec::new(); - - while quotient != 0 { - let rest = quotient % 10; - quotient /= 10; - p += 1; - if rest == 9 { - reverse_roman.push(RomanDigit::from(10_u32.pow(p))); - reverse_roman.push(RomanDigit::from(10_u32.pow(p - 1))); - } else if rest == 4 { - reverse_roman.push(RomanDigit::from(10_u32.pow(p) / 2)); - reverse_roman.push(RomanDigit::from(10_u32.pow(p - 1))); - } else if rest >= 5 { - let repetitions = rest - 5; - for _ in 0..repetitions { - reverse_roman.push(RomanDigit::from(10_u32.pow(p - 1))); - } - reverse_roman.push(RomanDigit::from(10_u32.pow(p) / 2)); + let mut acc = value; + + let it = iter::from_fn(|| { + if acc == 0 { + None } else { - for _ in 0..rest { - reverse_roman.push(RomanDigit::from(10_u32.pow(p - 1))) - } + Some(RomanDigit::take(&mut acc)) } - } + }) + .flatten(); - reverse_roman.reverse(); - RomanNumber(reverse_roman) + Self(it.collect()) } } -impl From for u32 { - fn from(n: RomanNumber) -> Self { - let mut result: u32 = 0; - - let numbers: Vec = n.0.iter().map(|i| u32::from(*i)).collect(); - - for (i, value) in numbers.iter().enumerate() { - result += value; - if i >= 1 && *value > numbers[i - 1] { - result = result - 2 * numbers[i - 1] - } - } +impl RomanNumber { + #[inline] + fn to_u32(&self) -> u32 { + u32::from(self) + } +} - result +impl From<&RomanNumber> for u32 { + #[inline] + fn from(n: &RomanNumber) -> Self { + n.0.iter() + .copied() + .map(|i| i as u32) + .fold((0, 0), |(sum, prev), curr| { + (sum + if prev < curr { curr - 2 * prev } else { curr }, curr) + }) + .0 } } impl Iterator for RomanNumber { - type Item = RomanNumber; + type Item = Self; + #[inline] fn next(&mut self) -> Option { - if self.0.len() == 0 { - return None; + if self.0.is_empty() { + None + } else { + Some(RomanNumber::from(self.to_u32() + 1)) } - - let mut aux = u32::from(self.clone()); - - aux = aux + 1; - - Some(RomanNumber::from(aux)) } } diff --git a/solutions/sales/Cargo.toml b/solutions/sales/Cargo.toml index 0e735edf..db6e0e85 100644 --- a/solutions/sales/Cargo.toml +++ b/solutions/sales/Cargo.toml @@ -2,7 +2,7 @@ name = "sales" version = "0.1.0" authors = ["lee "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/sales/src/lib.rs b/solutions/sales/src/lib.rs index 90cd5178..8570d1d1 100644 --- a/solutions/sales/src/lib.rs +++ b/solutions/sales/src/lib.rs @@ -1,234 +1,63 @@ -/* -## sales +#![feature(sort_floats)] -### Instructions +const ONE_FREE_EVERY: usize = 3; -You will have to create a shopping system, where you will have a : +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Item<'a>(pub &'a str, pub f64); -- Store that will save all the products in it -- Cart that will have `items`, that the client will buy, and a `receipt` - -This store is having a promotion, "Buy three and get one for free" (the free item must be the cheapest). The receipt must not present -any value as 0, so you will have to apply the promotion to all items instead. - -### Example - -`[1.23, 3.12, 23.1]` -> receipt will be `[1.17, 2.98, 22.07]` - -So `1.17 + 2.98 + 22.07 == 3.12 + 23.1 + 0` - -This is a percentage calculation, and it can be applied to a set of three items. -If the client purchase 9 items it will be applied the promotion, three for free, to all items - -|--------------| |---------------| |---------------| -`[1.23, 23.1, 3.12, 9.75, 1.75, 23.75, 2.75, 1.64, 15.23]` -> receipt will be `[1.16, 1.55, 1.65, 2.6, 2.94, 9.2, 14.38, 21.8, 22.42]` - -|--------| |--------| |--------| -`[3.12, 9.75, 1.75, 23.75, 2.75, 1.64, 15.23]` -> receipt will be `[1.54, 1.65, 2.59, 2.94, 9.18, 14.34, 22.36]` - -and so on... (hint: Closures is the way) - -You will have to implement for the Cart structure the following function: - -- `new`, that will initialize the cart -- `insert_item`, that will receive a reference to `Store` and a `String`. Just like the name says you will - have to insert the item to the cart -- `generate_receipt`, that returns a vector of sorted floats. This function must generate the receipt just -like the example above, using the promotion. Also saving the result in the filed `receipt`. - -```rust -fn main() { - let store = Store::new(vec![ - (String::from("product A"), 1.23), - (String::from("product B"), 23.1), - (String::from("product C"), 3.12)]); - - println!("{:?}", store); - // output: - // Store { products: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)] } - - let mut cart = Cart::new(); - cart.insert_item(&store, String::from("product A")); - cart.insert_item(&store, String::from("product B")); - cart.insert_item(&store, String::from("product C")); - println!("{:?}", cart.generate_receipt()); - // output: - // [1.17, 2.98, 22.07] - - println!("{:?}", cart); - // output: - // Cart { items: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)], receipt: [1.17, 2.98, 22.07] } -} -``` - -### Notions - -- https://doc.rust-lang.org/rust-by-example/fn/closures.html - -*/ - -#[derive(Debug, Clone, PartialEq)] -pub struct Store { - pub products: Vec<(String, f32)>, +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Store<'a, const N: usize> { + pub products: [Item<'a>; N], } -impl Store { - pub fn new(products: Vec<(String, f32)>) -> Store { - Store { products } +impl<'a, const N: usize> Store<'a, N> { + pub const fn new(products: [Item<'a>; N]) -> Self { + Self { products } } } -#[derive(Debug, Clone, PartialEq)] -pub struct Cart { - pub items: Vec<(String, f32)>, - pub receipt: Vec, +#[derive(Default, Debug, Clone, PartialEq)] +pub struct Cart<'a> { + pub items: Vec>, } -impl Cart { - pub fn new() -> Cart { - Cart { - items: vec![], - receipt: vec![], - } +impl<'a> Cart<'a> { + #[inline] + pub fn new() -> Self { + Self::default() } - pub fn insert_item(&mut self, s: &Store, ele: String) { - let pos = s.products.iter().position(|(x, _)| *x == ele).unwrap(); - self.items.push((ele, s.products[pos].1)); - } + pub fn insert_item_by_name( + &mut self, + s: &Store<'a, N>, + name: &str, + ) -> Result<(), ()> { + let item = s.products.iter().copied().find(|p| p.0 == name).ok_or(())?; + self.items.push(item); - pub fn get_prices(&self) -> Vec { - self.items.iter().map(|(_, v)| *v).collect::>() + Ok(()) } - pub fn generate_receipt(&mut self) -> Vec { - let mut prices = self.get_prices(); - let cal = self.items.len() / 3; - prices.sort_by(|a, b| a.partial_cmp(b).unwrap()); - - let v: Vec = prices[cal..].to_vec(); - - let percentage: f32 = - (v.iter().sum::() * 100.0) as f32 / prices.iter().sum::() as f32; - - self.receipt = prices + pub fn generate_prices(&self) -> Vec { + let mut prices = self + .items .iter() - .map(|price| round_two(price * percentage / 100.0)) - .collect::>(); - - self.receipt.clone() - } -} - -fn round_two(nbr: f32) -> f32 { - (nbr * 100.0).round() / 100.0 -} + .copied() + .map(|Item(_, v)| v) + .collect::>(); + prices.sort_floats(); -#[cfg(test)] -mod tests { - use super::*; - - #[derive(Debug)] - struct Tests { - store: Store, - carts: Vec<(Cart, Vec)>, - } - - fn add_items(s: &Store, items: Vec<&str>, c: &mut Cart) { - for item in items.iter() { - c.insert_item(s, item.to_string()); - } - } - - impl Tests { - fn new() -> Tests { - let store = Store::new(vec![ - (String::from("product A"), 1.23), - (String::from("product B"), 23.1), - (String::from("product C"), 3.12), - (String::from("product D"), 9.75), - (String::from("product E"), 1.75), - (String::from("product F"), 23.75), - (String::from("product G"), 2.75), - (String::from("product H"), 1.64), - (String::from("product I"), 15.23), - (String::from("product J"), 2.10), - (String::from("product K"), 54.91), - (String::from("product L"), 43.99), - ]); - - let mut c = Cart::new(); - let mut c1 = Cart::new(); - let mut c2 = Cart::new(); - let mut c3 = Cart::new(); - add_items(&store, vec!["product A", "product B", "product C"], &mut c); - let sol = vec![1.17, 2.98, 22.06]; - add_items( - &store, - vec![ - "product A", - "product B", - "product C", - "product D", - "product E", - "product F", - "product G", - ], - &mut c1, - ); - let sol1 = vec![1.17, 1.67, 2.62, 2.98, 9.31, 22.05, 22.67]; - add_items( - &store, - vec![ - "product A", - "product B", - "product C", - "product D", - "product E", - "product F", - "product G", - "product H", - "product I", - ], - &mut c2, - ); - let sol2 = vec![1.16, 1.55, 1.65, 2.6, 2.94, 9.2, 14.38, 21.8, 22.42]; - add_items( - &store, - vec![ - "product A", - "product B", - "product C", - "product D", - "product E", - "product F", - "product G", - "product H", - "product I", - "product J", - "product K", - "product L", - ], - &mut c3, - ); - let sol3 = vec![ - 1.18, 1.58, 1.69, 2.02, 2.65, 3.01, 9.39, 14.67, 22.25, 22.88, 42.38, 52.9, - ]; - - Tests { - store, - carts: vec![(c, sol), (c1, sol1), (c2, sol2), (c3, sol3)], - } - } - } + let all_total = prices.iter().sum::(); + let non_discount_total = prices + .iter() + .skip(prices.len() / ONE_FREE_EVERY) + .sum::(); - #[test] - fn test_generate_receipt() { - let cases = Tests::new(); + let percentage = (non_discount_total * 100.) / all_total; - for (mut c, sol) in cases.carts.into_iter() { - assert_eq!(c.generate_receipt(), sol); - assert_eq!(c.receipt, sol); - } + prices + .into_iter() + .map(|p| (p * percentage).round() / 100.) + .collect() } } diff --git a/solutions/slices_to_map/Cargo.toml b/solutions/slices_to_map/Cargo.toml index bbb2f64f..a793a37f 100644 --- a/solutions/slices_to_map/Cargo.toml +++ b/solutions/slices_to_map/Cargo.toml @@ -2,7 +2,7 @@ name = "slices_to_map" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/slices_to_map/src/lib.rs b/solutions/slices_to_map/src/lib.rs index 2392d88d..8db39874 100644 --- a/solutions/slices_to_map/src/lib.rs +++ b/solutions/slices_to_map/src/lib.rs @@ -1,75 +1,6 @@ -// # Instructions: -// Create a function that borrows two slices (&[T]) and returns a hashmap where -// the first slice represents the keys and the second represents the values. +use std::{collections::HashMap, hash::Hash}; -// The signature of the function is the following -// fn slices_to_map<'a, T: Hash + Eq, U>(keys: &'a [T], values: &'a [U]) -> HashMap<&'a T, &'a U> { - -// # Example: -// for the slices &["hello", "how", "are", "you"] &[1, 3, 5, 8] -// returns the hashmap ["hello": 1, "how": 3, "are": 5, "you":8] - -use std::cmp::Eq; -use std::collections::HashMap; -use std::hash::Hash; - -pub fn slices_to_map<'a, T: Hash + Eq, U>(keys: &'a [T], values: &'a [U]) -> HashMap<&'a T, &'a U> { - keys.iter().zip(values).collect() -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_same_length() { - let keys = ["Olivia", "Liam", "Emma", "Noah", "James"]; - let values = [1, 3, 23, 5, 2]; - let mut expected = HashMap::new(); - expected.insert(&"Olivia", &1); - expected.insert(&"Liam", &3); - expected.insert(&"Emma", &23); - expected.insert(&"Noah", &5); - expected.insert(&"James", &2); - assert_eq!(slices_to_map(&keys, &values), expected); - } - - #[test] - fn test_different_length() { - let keys = ["Olivia", "Liam", "Emma", "Noah", "James"]; - let values = [1, 3, 23, 5, 2, 9]; - let mut expected = HashMap::new(); - expected.insert(&"Olivia", &1); - expected.insert(&"Liam", &3); - expected.insert(&"Emma", &23); - expected.insert(&"Noah", &5); - expected.insert(&"James", &2); - assert_eq!(slices_to_map(&keys, &values), expected); - - let keys = ["Olivia", "Liam", "Emma", "Noah", "James", "Isabella"]; - let values = [1, 3, 23, 5, 2]; - assert_eq!(slices_to_map(&keys, &values), expected); - } - - #[test] - fn it_works_for_vecs() { - let mut expected = HashMap::new(); - expected.insert(&"Olivia", &1); - expected.insert(&"Liam", &3); - expected.insert(&"Emma", &23); - expected.insert(&"Noah", &5); - expected.insert(&"James", &2); - - let keys = ["Olivia", "Liam", "Emma", "Noah", "James"]; - let values = [1, 3, 23, 5, 2]; - - assert_eq!(slices_to_map(&keys, &values), expected); - let keys = vec!["Olivia", "Liam", "Emma", "Noah", "James"]; - let values = vec![1, 3, 23, 5, 2, 9]; - assert_eq!(slices_to_map(&keys, &values), expected); - - let keys = vec!["Olivia", "Liam", "Emma", "Noah", "James", "Isabella"]; - let values = vec![1, 3, 23, 5, 2]; - assert_eq!(slices_to_map(&keys, &values), expected); - } +#[inline] +pub fn slices_to_map(keys: &[T], values: &[U]) -> HashMap { + keys.iter().copied().zip(values.iter().copied()).collect() } diff --git a/solutions/step_iterator/Cargo.toml b/solutions/step_iterator/Cargo.toml index 6c7f3dce..88c90afa 100644 --- a/solutions/step_iterator/Cargo.toml +++ b/solutions/step_iterator/Cargo.toml @@ -2,7 +2,7 @@ name = "step_iterator" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/step_iterator/src/lib.rs b/solutions/step_iterator/src/lib.rs index 9c60ae84..fe58568f 100644 --- a/solutions/step_iterator/src/lib.rs +++ b/solutions/step_iterator/src/lib.rs @@ -1,102 +1,37 @@ -// Create an Iterator (by implementing the std::iter::Iterator trait) -// that iterates through the values from beg to end (including end) in -// the indicated steps +use std::ops::{Add, AddAssign}; -// The name of you're iterator will be StepIterator and it must be -// generic so you can use any integer value: i8,..,i64 of floating -// point number f32,..,f64 - -// Define the associated function: `new` that creates a new Step iterator: -// fn new(beg: T, end: T, step: T) -> StepIterator - -// For example: -// for v in StepIterator::new(0, 100, 10) { -// println!("{}", v); -// } -// must print: -// 0 -// 10 -// 20 -// 30 -// 40 -// 50 -// 60 -// 70 -// 80 -// 90 -// 100 - -// If the steps don't allow to arrive until the end of the sequence -// only the last value inferior than the end of the series will be returned -// Like beg: 0, end: 100, steps: 7 the last number returned will be -// the last number returned will be 98 - -pub struct StepIterator { - beg: T, +pub struct StepIterator + AddAssign + Copy + Clone> { started: bool, + curr: T, end: T, step: T, } -use std::ops::Add; -impl + PartialOrd + PartialEq> StepIterator { - pub fn new(beg: T, end: T, step: T) -> Self { +impl + AddAssign + Copy + Clone> StepIterator { + pub const fn new(beg: T, end: T, step: T) -> Self { Self { - beg, started: false, + curr: beg, end, step, } } } -impl + PartialOrd + Copy> std::iter::Iterator for StepIterator { +impl + AddAssign + Copy + Clone> Iterator for StepIterator { type Item = T; + fn next(&mut self) -> Option { - if self.beg > self.end || self.beg + self.step > self.end { + if self.curr > self.end || self.curr + self.step > self.end { return None; } - if !self.started { - self.started = true; - return Some(self.beg); - } - self.beg = self.beg + self.step; - Some(self.beg) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_next() { - let mut step_iterator = StepIterator::new(0, 100, 10); - assert_eq!(step_iterator.next(), Some(0)); - assert_eq!(step_iterator.next(), Some(10)); - } - - #[test] - fn until_the_end() { - for (i, v) in StepIterator::new(0, 100, 10).enumerate() { - println!("position: {}, value: {}, ", i, v); - assert_eq!(i * 10, v); - } - } - #[test] - fn test_with_floats() { - for (i, v) in StepIterator::new(0.0, 10.0, 0.5).enumerate() { - println!("position: {}, value: {}, ", i, v); - assert_eq!(i as f64 * 0.5, v); + if self.started { + self.curr += self.step; + } else { + self.started = true; } - } - #[test] - fn test_with_floats_with_imperfect_range() { - for (i, v) in StepIterator::new(0.3, 10.0, 0.5).enumerate() { - println!("position: {}, value: {}, ", i, v); - assert_eq!(i as f64 * 0.5 + 0.3, v); - } + Some(self.curr) } } diff --git a/tests/adding_test/Cargo.toml b/tests/adding_test/Cargo.toml index bb1c39a0..0397860b 100644 --- a/tests/adding_test/Cargo.toml +++ b/tests/adding_test/Cargo.toml @@ -2,7 +2,7 @@ name = "adding_test" version = "0.1.0" authors = ["MSilva95 "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/adding_test/src/main.rs b/tests/adding_test/src/lib.rs similarity index 77% rename from tests/adding_test/src/main.rs rename to tests/adding_test/src/lib.rs index 43f1d7fe..bfd69c7f 100644 --- a/tests/adding_test/src/main.rs +++ b/tests/adding_test/src/lib.rs @@ -1,26 +1,6 @@ -/* -## adding - -### Instructions - -Create the function `add_curry` that returns a closure. -The purpose is to curry the add method to create more variations. - -*/ -use adding::*; -fn main() { - let add10 = add_curry(-10); - let add20 = add_curry(2066); - let add30 = add_curry(300000); - - println!("{}", add10(5)); - println!("{}", add20(195)); - println!("{}", add30(5696)); -} - #[cfg(test)] mod tests { - use super::*; + use adding::*; #[test] fn test_zero() { @@ -60,6 +40,7 @@ mod tests { assert_eq!(add250(463), 713); assert_eq!(add250(400000000), 400000250); } + #[test] fn test_add3960() { let add3960 = add_curry(3960); diff --git a/tests/adding_twice_test/Cargo.toml b/tests/adding_twice_test/Cargo.toml index 298325ac..83f3b111 100644 --- a/tests/adding_twice_test/Cargo.toml +++ b/tests/adding_twice_test/Cargo.toml @@ -2,7 +2,7 @@ name = "adding_twice_test" version = "0.1.0" authors = ["MSilva95 "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/adding_twice_test/src/main.rs b/tests/adding_twice_test/src/lib.rs similarity index 61% rename from tests/adding_twice_test/src/main.rs rename to tests/adding_twice_test/src/lib.rs index 18f555b7..a087f422 100644 --- a/tests/adding_twice_test/src/main.rs +++ b/tests/adding_twice_test/src/lib.rs @@ -1,40 +1,6 @@ -/* -## adding_twice - -### Instructions - -In this exercise you will have to reuse your `add_curry` function -Then you have to complete the function `twice` using closures, this function will -take a function f(x) as parameter and return a function f(f(x)) -So, the purpose of this function is to add two times the value in `add_curry` -to the original value. - - ### Notions - -- https://doc.rust-lang.org/rust-by-example/fn/hof.html#higher-order-functions -*/ -use adding_twice::*; -fn main() { - let add10 = add_curry(10); - let value = twice(add10); - println!("The value is {}", value(7)); - - let add20 = add_curry(20); - let value = twice(add20); - println!("The value is {}", value(7)); - - let add30 = add_curry(30); - let value = twice(add30); - println!("The value is {}", value(7)); - - let neg = add_curry(-32); - let value = twice(neg); - println!("{}", value(7)); -} - #[cfg(test)] mod tests { - use super::*; + use adding_twice::*; #[test] fn test_zero_twice() { @@ -63,6 +29,7 @@ mod tests { assert_eq!(value(463), 483); assert_eq!(value(400000000), 400000020); } + #[test] fn test_add20_twice() { let value = twice(add_curry(20)); @@ -73,6 +40,7 @@ mod tests { assert_eq!(value(463), 503); assert_eq!(value(400000000), 400000040); } + #[test] fn test_add30_twice() { let value = twice(add_curry(30)); diff --git a/tests/closures_test/Cargo.toml b/tests/closures_test/Cargo.toml index 56790782..b14ec84e 100644 --- a/tests/closures_test/Cargo.toml +++ b/tests/closures_test/Cargo.toml @@ -2,7 +2,7 @@ name = "closures_test" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/closures_test/src/lib.rs b/tests/closures_test/src/lib.rs new file mode 100644 index 00000000..721bc55d --- /dev/null +++ b/tests/closures_test/src/lib.rs @@ -0,0 +1,17 @@ +#[cfg(test)] +mod tests { + use closures::*; + + #[test] + fn test() { + assert_eq!( + [ + 4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576, 676, 784, 900, 1024, 1156, + 1296, 1444, 1600, 1764, 1936, 2116, 2304, 2500, 2704, 2916, 3136, 3364, 3600, 3844, + 4096, 4356, 4624, 4900, 5184, 5476, 5776, 6084, 6400, 6724, 7056, 7396, 7744, 8100, + 8464, 8836, 9216, 9604, 10000 + ], + first_fifty_even_square().as_slice() + ); + } +} diff --git a/tests/closures_test/src/main.rs b/tests/closures_test/src/main.rs deleted file mode 100644 index 5ee55d23..00000000 --- a/tests/closures_test/src/main.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Using closures and iterators create a function, -// first_fifty_even_square() that returns the -// first 50 pair numbers squares that it's [4, 16, 36, ..., 10000]. - -use closures::*; - -fn main() { - println!("Hello, world!"); - let v1 = first_fifty_even_square(); - - println!("All elements in {:?}, len = {}", v1, v1.len()); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test() { - let v1 = vec![ - 4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576, 676, 784, 900, 1024, 1156, 1296, - 1444, 1600, 1764, 1936, 2116, 2304, 2500, 2704, 2916, 3136, 3364, 3600, 3844, 4096, - 4356, 4624, 4900, 5184, 5476, 5776, 6084, 6400, 6724, 7056, 7396, 7744, 8100, 8464, - 8836, 9216, 9604, 10000, - ]; - assert_eq!(v1, first_fifty_even_square()); - } -} diff --git a/tests/get_products_test/Cargo.toml b/tests/get_products_test/Cargo.toml index 91261ee7..07364a43 100644 --- a/tests/get_products_test/Cargo.toml +++ b/tests/get_products_test/Cargo.toml @@ -2,7 +2,7 @@ name = "get_products_test" version = "0.1.0" authors = ["MSilva95 "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/get_products_test/src/lib.rs b/tests/get_products_test/src/lib.rs new file mode 100644 index 00000000..fde5ad5a --- /dev/null +++ b/tests/get_products_test/src/lib.rs @@ -0,0 +1,20 @@ +#[cfg(test)] +mod tests { + use get_products::*; + + #[test] + fn test_multiple() { + assert_eq!(get_products([1, 7, 3, 4]), [84, 12, 28, 21]); + assert_eq!(get_products([10, 3, 5, 6, 2]), [180, 600, 360, 300, 900]); + } + + #[test] + fn test_empty_case() { + assert_eq!(get_products([]), []); + } + + #[test] + fn test_single_case() { + assert_eq!(get_products([99]), [1]); + } +} diff --git a/tests/get_products_test/src/main.rs b/tests/get_products_test/src/main.rs deleted file mode 100644 index 2917b01b..00000000 --- a/tests/get_products_test/src/main.rs +++ /dev/null @@ -1,49 +0,0 @@ -/* -## get_products - -### Instructions - -Create a function `get_products` that takes a vector of integers, and returns a vector of the products -of each index. For this exercise to be correct you will have to return the product of every index -except the current one. - -### Example: - -Input: arr[] = {10, 3, 5, 6, 2} -Output: prod[] = {180, 600, 360, 300, 900} - -*/ -use get_products::*; -fn main() { - let arr: Vec = vec![1, 7, 3, 4]; - let output = get_products(arr); - println!("{:?}", output); -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn test_multiple() { - let arr: Vec = vec![1, 7, 3, 4]; - let output = get_products(arr); - let arr2: Vec = vec![10, 3, 5, 6, 2]; - let output2 = get_products(arr2); - assert_eq!(output, vec![84, 12, 28, 21]); - assert_eq!(output2, vec![180, 600, 360, 300, 900]); - } - - #[test] - fn test_empty_case() { - let arr: Vec = Vec::new(); - let output = get_products(arr); - assert_eq!(output, vec![]); - } - - #[test] - fn test_single_case() { - let arr: Vec = vec![2]; - let output = get_products(arr); - assert_eq!(output, vec![]); - } -} diff --git a/tests/highest_test/Cargo.toml b/tests/highest_test/Cargo.toml index 0fa3e40b..1c694f36 100644 --- a/tests/highest_test/Cargo.toml +++ b/tests/highest_test/Cargo.toml @@ -2,7 +2,7 @@ name = "highest_test" version = "0.1.0" authors = ["MSilva95 "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/highest_test/src/lib.rs b/tests/highest_test/src/lib.rs new file mode 100644 index 00000000..5c9905cf --- /dev/null +++ b/tests/highest_test/src/lib.rs @@ -0,0 +1,42 @@ +#[cfg(test)] +mod tests { + use highest::*; + + #[test] + fn test_inner() { + let expected = [30, 50, 20, 70]; + let n = Numbers::new(expected); + assert_eq!(n.inner(), &expected); + } + + #[test] + fn test_latest() { + assert_eq!(Numbers::new([100, 0, 90, 30]).latest(), Some(30)); + assert_eq!(Numbers::new([]).latest(), None); + } + + #[test] + fn test_highest() { + assert_eq!(Numbers::new([40, 100, 70]).highest(), Some(100)); + assert_eq!(Numbers::new([]).highest(), None); + } + + #[test] + fn test_highest_three() { + assert_eq!( + Numbers::new([10, 30, 90, 30, 100, 20, 10, 0, 30, 40, 40, 70, 70]).highest_three(), + Some([100, 90, 70]) + ); + assert_eq!( + Numbers::new([40, 20, 40, 30]).highest_three(), + Some([40, 40, 30]) + ); + assert_eq!(Numbers::new([30, 70]).highest_three(), None); + assert_eq!(Numbers::new([40]).highest_three(), None); + assert_eq!(Numbers::new([]).highest_three(), None); + assert_eq!( + Numbers::new([20, 10, 30]).highest_three(), + Some([30, 20, 10]) + ); + } +} diff --git a/tests/highest_test/src/main.rs b/tests/highest_test/src/main.rs deleted file mode 100644 index 3650471f..00000000 --- a/tests/highest_test/src/main.rs +++ /dev/null @@ -1,80 +0,0 @@ -/* -## highest - -### Instructions - - In this exercise you will be given a `Numbers` struct. - Your task is to write these methods: - `list` that returns an `array` with every number in the struct - `latest` that returns an `Option` with the last added number - `highest` that return an `Option` with the highest number from the list, - `highest_three` that returns a `Vec` with the three highest numbers. - - ### Notions - -- https://doc.rust-lang.org/book/ch13-02-iterators.html - -*/ -use highest::*; - -fn main() { - let expected = [30, 500, 20, 70]; - let n = Numbers::new(&expected); - println!("{:?}", n.list()); - - println!("{:?}", n.highest()); - println!("{:?}", n.latest()); - println!("{:?}", n.highest_three()); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_list() { - let expected = [30, 50, 20, 70]; - let n = Numbers::new(&expected); - assert_eq!(n.list(), &expected); - } - - #[test] - fn test_latest() { - let n = Numbers::new(&[100, 0, 90, 30]); - let f = Numbers::new(&[]); - assert_eq!(n.latest(), Some(30)); - assert!( - f.latest().is_none(), - "It should have been None, {:?}", - f.latest() - ); - } - - #[test] - fn test_highest() { - let n = Numbers::new(&[40, 100, 70]); - let f = Numbers::new(&[]); - assert_eq!(n.highest(), Some(100)); - assert!( - f.highest().is_none(), - "It should have been None, {:?}", - f.highest() - ); - } - - #[test] - fn test_highest_three() { - let e = Numbers::new(&[10, 30, 90, 30, 100, 20, 10, 0, 30, 40, 40, 70, 70]); - let f = Numbers::new(&[40, 20, 40, 30]); - let g = Numbers::new(&[30, 70]); - let h = Numbers::new(&[40]); - let i = Numbers::new(&[]); - let j = Numbers::new(&[20, 10, 30]); - assert_eq!(e.highest_three(), vec![100, 90, 70]); - assert_eq!(f.highest_three(), vec![40, 40, 30]); - assert_eq!(g.highest_three(), vec![70, 30]); - assert_eq!(h.highest_three(), vec![40]); - assert!(i.highest_three().is_empty()); - assert_eq!(j.highest_three(), vec![30, 20, 10]); - } -} diff --git a/tests/iterators_test/Cargo.toml b/tests/iterators_test/Cargo.toml index 870294ed..e34dad6b 100644 --- a/tests/iterators_test/Cargo.toml +++ b/tests/iterators_test/Cargo.toml @@ -2,7 +2,7 @@ name = "iterators_test" version = "0.1.0" authors = ["MSilva95 "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/iterators_test/src/lib.rs b/tests/iterators_test/src/lib.rs new file mode 100644 index 00000000..3f042ed4 --- /dev/null +++ b/tests/iterators_test/src/lib.rs @@ -0,0 +1,46 @@ +#[cfg(test)] +mod tests { + use std::iter::zip; + + use iterators::*; + + #[test] + fn test_first_seven() { + let inputs = [1, 2, 3, 4, 5, 6, 7]; + let expected = [0, 1, 7, 2, 5, 8, 16]; + + for (v, r) in zip(inputs, expected) { + assert_eq!(collatz(v), Some(r)); + } + } + + #[test] + fn test_big_numbers() { + let inputs = [54, 888, 4372, 9999]; + let expected = [112, 72, 33, 91]; + + for (v, r) in zip(inputs, expected) { + assert_eq!(collatz(v), Some(r)); + } + } + + #[test] + fn test_zero() { + assert_eq!(collatz(0), None); + } + + #[test] + fn test_overflow() { + let inputs = [ + 6148914691236517207, + 6148914691236517209, + 6148914691236517211, + 6148914691236517213, + 6148914691236517215, + ]; + + for v in inputs { + assert_eq!(collatz(v), None); + } + } +} diff --git a/tests/iterators_test/src/main.rs b/tests/iterators_test/src/main.rs deleted file mode 100644 index 30476e23..00000000 --- a/tests/iterators_test/src/main.rs +++ /dev/null @@ -1,54 +0,0 @@ -use iterators::Collatz; -use iterators::*; - -fn main() { - println!("{:?}", collatz(4)); - println!("{:?}", collatz(5)); - println!("{:?}", collatz(6)); - println!("{:?}", collatz(7)); - println!("{:?}", collatz(12)); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_first_seven() { - let test_value = vec![1, 2, 3, 4, 5, 6, 7]; - let test_result = vec![0, 1, 7, 2, 5, 8, 16]; - - for i in 0..test_value.len() { - assert_eq!(test_result[i], collatz(test_value[i])); - } - } - - #[test] - fn test_big_numbers() { - let test_value = vec![54, 888, 4372, 9999]; - let test_result = vec![112, 72, 33, 91]; - - for i in 0..test_value.len() { - assert_eq!(test_result[i], collatz(test_value[i])); - } - } - - #[test] - fn test_iterator_for_loop() { - let aux = Collatz::new(133); - let sequence = vec![ - 133, 400, 200, 100, 50, 25, 76, 38, 19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, - 20, 10, 5, 16, 8, 4, 2, 1, - ]; - - for (i, value) in aux.enumerate() { - assert_eq!(value.v, sequence[i]); - } - } - - #[test] - fn test_iterator_count() { - let nb = Collatz::new(133); - assert_eq!(nb.count(), 28); - } -} diff --git a/tests/markdown_to_html_test/Cargo.toml b/tests/markdown_to_html_test/Cargo.toml index a15a99b4..4d0cf52d 100644 --- a/tests/markdown_to_html_test/Cargo.toml +++ b/tests/markdown_to_html_test/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "markdown_to_html_test" version = "0.1.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +pretty_assertions = "*" markdown_to_html = { path = "../../solutions/markdown_to_html" } diff --git a/tests/markdown_to_html_test/src/lib.rs b/tests/markdown_to_html_test/src/lib.rs new file mode 100644 index 00000000..86e00663 --- /dev/null +++ b/tests/markdown_to_html_test/src/lib.rs @@ -0,0 +1,37 @@ +#[cfg(test)] +mod tests { + use markdown_to_html::*; + use pretty_assertions::assert_eq; + + #[test] + fn test_subject_example() { + assert_eq!( + markdown_to_html(include_str!("./tests/example.md")), + include_str!("./tests/example.html") + ); + } + + #[test] + fn test_titles() { + assert_eq!( + markdown_to_html(include_str!("./tests/titles.md")), + include_str!("./tests/titles.html") + ); + } + + #[test] + fn test_bold_italic() { + assert_eq!( + markdown_to_html(include_str!("./tests/bold_italic.md")), + include_str!("./tests/bold_italic.html") + ); + } + + #[test] + fn test_blockquotes() { + assert_eq!( + markdown_to_html(include_str!("./tests/blockquotes.md")), + include_str!("./tests/blockquotes.html") + ); + } +} diff --git a/tests/markdown_to_html_test/src/main.rs b/tests/markdown_to_html_test/src/main.rs deleted file mode 100644 index 8d1bff08..00000000 --- a/tests/markdown_to_html_test/src/main.rs +++ /dev/null @@ -1,89 +0,0 @@ -use markdown_to_html::*; - -const EXAMPLE: &str = "# This is a nice converter - - ## It handle *all* titles - -## From # to ### with no problems - -### With attention to details ;) -###With attention to details ;) - -> Blockquotes are handled too ->if well formatted of course - -And **bold** and *italics* of course work as well. - -**** - -**bold on -multiple -lines -also**"; - -fn main() { - println!("{}", markdown_to_html(EXAMPLE)); -} - -#[cfg(test)] -mod tests { - use super::*; - - const EXAMPLE_HTML: &str = "

This is a nice converter

- -

It handle all titles

- -

From # to ### with no problems

- -

With attention to details ;)

-###With attention to details ;) - -
Blockquotes are handled too
->if well formatted of course - -And bold and italics of course work as well. - - - -bold on -multiple -lines -also"; - - #[test] - fn test_subject_example() { - assert_eq!(markdown_to_html(EXAMPLE), EXAMPLE_HTML); - } - - const TITLES: &str = "# first title -## second title -### third title - -#not valid title - # valid title with no new line"; - - const TITLES_HTML: &str = "

first title

-

second title

-

third title

- -#not valid title -

valid title with no new line

-"; - - #[test] - fn test_titles() { - assert_eq!(markdown_to_html(TITLES), TITLES_HTML); - } - - const STRONG_ITALIC: &str = "**bold** and *italic* text -## Nested in ** a title ** element *do work*"; - - const STRONG_ITALIC_HTML: &str = "bold and italic text -

Nested in a title element do work

-"; - - #[test] - fn test_strong_italic() { - assert_eq!(markdown_to_html(STRONG_ITALIC), STRONG_ITALIC_HTML); - } -} diff --git a/tests/markdown_to_html_test/src/tests/blockquotes.html b/tests/markdown_to_html_test/src/tests/blockquotes.html new file mode 100644 index 00000000..1918fda6 --- /dev/null +++ b/tests/markdown_to_html_test/src/tests/blockquotes.html @@ -0,0 +1,2 @@ +
Blockquotes are handled too
+>if well formatted of course \ No newline at end of file diff --git a/tests/markdown_to_html_test/src/tests/blockquotes.md b/tests/markdown_to_html_test/src/tests/blockquotes.md new file mode 100644 index 00000000..1fbb70b0 --- /dev/null +++ b/tests/markdown_to_html_test/src/tests/blockquotes.md @@ -0,0 +1,2 @@ +> Blockquotes are handled too +>if well formatted of course \ No newline at end of file diff --git a/tests/markdown_to_html_test/src/tests/bold_italic.html b/tests/markdown_to_html_test/src/tests/bold_italic.html new file mode 100644 index 00000000..e7faba4b --- /dev/null +++ b/tests/markdown_to_html_test/src/tests/bold_italic.html @@ -0,0 +1,2 @@ +bold and italic text +

Nested in a title element do work

\ No newline at end of file diff --git a/tests/markdown_to_html_test/src/tests/bold_italic.md b/tests/markdown_to_html_test/src/tests/bold_italic.md new file mode 100644 index 00000000..d0ec05a8 --- /dev/null +++ b/tests/markdown_to_html_test/src/tests/bold_italic.md @@ -0,0 +1,2 @@ +**bold** and *italic* text +## Nested in ** a title ** element *do work* diff --git a/tests/markdown_to_html_test/src/tests/example.html b/tests/markdown_to_html_test/src/tests/example.html new file mode 100644 index 00000000..451c4921 --- /dev/null +++ b/tests/markdown_to_html_test/src/tests/example.html @@ -0,0 +1,14 @@ +

This is a nice converter

+

It handles all titles

+

From # to ### with no problems

+

With attention to details ;)

+###With attention to details ;) +
Blockquotes are handled too
+>if well formatted of course +
test!
+And bold and italics of course work as well. +
+bold on +multiple +lines +also \ No newline at end of file diff --git a/tests/markdown_to_html_test/src/tests/example.md b/tests/markdown_to_html_test/src/tests/example.md new file mode 100644 index 00000000..9d706bba --- /dev/null +++ b/tests/markdown_to_html_test/src/tests/example.md @@ -0,0 +1,24 @@ +# This is a nice converter + + ## It handles *all* titles + +## From # to ### with no problems + +### With attention to details ;) +###With attention to details ;) + +> Blockquotes are handled too +>if well formatted of course +> test! + + And **bold** and *italics* of course work as well. + +**** + +**bold on +multiple +lines + + +also** + diff --git a/tests/markdown_to_html_test/src/tests/titles.html b/tests/markdown_to_html_test/src/tests/titles.html new file mode 100644 index 00000000..59647f2b --- /dev/null +++ b/tests/markdown_to_html_test/src/tests/titles.html @@ -0,0 +1,5 @@ +

first title

+

second title

+

third title

+#not valid title +

valid title with space and no new line

\ No newline at end of file diff --git a/tests/markdown_to_html_test/src/tests/titles.md b/tests/markdown_to_html_test/src/tests/titles.md new file mode 100644 index 00000000..73c1a482 --- /dev/null +++ b/tests/markdown_to_html_test/src/tests/titles.md @@ -0,0 +1,6 @@ +# first title +## second title +### third title + +#not valid title + # valid title with space and no new line \ No newline at end of file diff --git a/tests/project_motion_test/Cargo.toml b/tests/project_motion_test/Cargo.toml index 37231c01..b8b8d4d6 100644 --- a/tests/project_motion_test/Cargo.toml +++ b/tests/project_motion_test/Cargo.toml @@ -2,9 +2,10 @@ name = "project_motion_test" version = "0.1.0" authors = ["lee "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +pretty_assertions = "*" project_motion = { path = "../../solutions/project_motion"} diff --git a/tests/project_motion_test/src/lib.rs b/tests/project_motion_test/src/lib.rs new file mode 100644 index 00000000..c79e9bcb --- /dev/null +++ b/tests/project_motion_test/src/lib.rs @@ -0,0 +1,92 @@ +#[cfg(test)] +mod tests { + use pretty_assertions::assert_eq; + use project_motion::*; + + #[test] + fn test_without_initial_velocity() { + assert_eq!( + ThrownObject::new(Vec2 { x: 50., y: 50. }, Vec2 { x: 0., y: 0. }).collect::>(), + [ + (Vec2 { x: 50., y: 45.1 }, Vec2 { x: 0., y: -9.8 }), + (Vec2 { x: 50., y: 30.4 }, Vec2 { x: 0., y: -19.6 }), + ( + Vec2 { + x: 50., + y: 5.899999999999999 + }, + Vec2 { + x: 0., + y: -29.400000000000002 + } + ), + ] + ); + } + + #[test] + fn test_with_velocity() { + assert_eq!( + ThrownObject::new(Vec2 { x: 0., y: 50. }, Vec2 { x: 10., y: 10. }).collect::>(), + [ + ( + Vec2 { x: 10., y: 55.1 }, + Vec2 { + x: 10., + y: 0.1999999999999993 + } + ), + ( + Vec2 { x: 20., y: 50.4 }, + Vec2 { + x: 10., + y: -9.600000000000001 + } + ), + ( + Vec2 { x: 30., y: 35.9 }, + Vec2 { + x: 10., + y: -19.400000000000002 + } + ), + ( + Vec2 { + x: 40., + y: 11.599999999999994 + }, + Vec2 { + x: 10., + y: -29.200000000000003 + } + ) + ] + ); + } + + #[test] + fn test_with_negative_velocity() { + assert_eq!( + ThrownObject::new(Vec2 { x: -10., y: 50. }, Vec2 { x: -10., y: -10. }) + .collect::>(), + [ + (Vec2 { x: -20., y: 35.1 }, Vec2 { x: -10., y: -19.8 }), + ( + Vec2 { + x: -30., + y: 10.399999999999999 + }, + Vec2 { x: -10., y: -29.6 } + ), + ] + ); + } + + #[test] + fn test_with_zero() { + assert_eq!( + ThrownObject::new(Vec2 { x: 0., y: 0. }, Vec2 { x: 0., y: 0. }).collect::>(), + [] + ); + } +} diff --git a/tests/project_motion_test/src/main.rs b/tests/project_motion_test/src/main.rs deleted file mode 100644 index fb258138..00000000 --- a/tests/project_motion_test/src/main.rs +++ /dev/null @@ -1,143 +0,0 @@ -use project_motion::*; - -fn main() { - let mut obj = ThrowObject::new(Object { x: 50.0, y: 50.0 }, Object { x: 0.0, y: 0.0 }); - println!("{:?}", obj.next()); - println!("{:?}", obj.next()); - println!("{:?}", obj.next()); - println!("{:?}", obj.next()); - println!("{:?}", obj.next()); -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn test_without_acelaration_velocity() { - let mut obj = ThrowObject::new(Object { x: 50.0, y: 50.0 }, Object { x: 0.0, y: 0.0 }); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 50.0, y: 50.0 }, - init_velocity: Object { x: 0.0, y: 0.0 }, - actual_position: Object { x: 50.0, y: 45.1 }, - actual_velocity: Object { x: 0.0, y: -9.8 }, - time: 1.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 50.0, y: 50.0 }, - init_velocity: Object { x: 0.0, y: 0.0 }, - actual_position: Object { x: 50.0, y: 30.4 }, - actual_velocity: Object { x: 0.0, y: -19.6 }, - time: 2.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 50.0, y: 50.0 }, - init_velocity: Object { x: 0.0, y: 0.0 }, - actual_position: Object { x: 50.0, y: 5.9 }, - actual_velocity: Object { x: 0.0, y: -29.4 }, - time: 3.0, - }) - ); - - assert!(obj.next().is_none(), "{:?} instead of None", obj); - - assert!(obj.next().is_none(), "{:?} instead of None", obj); - } - - #[test] - fn test_with_velocity() { - let mut obj = ThrowObject::new(Object { x: 0.0, y: 50.0 }, Object { x: 10.0, y: 10.0 }); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 50.0 }, - init_velocity: Object { x: 10.0, y: 10.0 }, - actual_position: Object { x: 10.0, y: 55.1 }, - actual_velocity: Object { x: 10.0, y: 0.2 }, - time: 1.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 50.0 }, - init_velocity: Object { x: 10.0, y: 10.0 }, - actual_position: Object { x: 20.0, y: 50.4 }, - actual_velocity: Object { x: 10.0, y: -9.6 }, - time: 2.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 50.0 }, - init_velocity: Object { x: 10.0, y: 10.0 }, - actual_position: Object { x: 30.0, y: 35.9 }, - actual_velocity: Object { x: 10.0, y: -19.4 }, - time: 3.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: 0.0, y: 50.0 }, - init_velocity: Object { x: 10.0, y: 10.0 }, - actual_position: Object { x: 40.0, y: 11.6 }, - actual_velocity: Object { x: 10.0, y: -29.2 }, - time: 4.0, - }) - ); - - assert!(obj.next().is_none(), "{:?} instead of None", obj); - } - - #[test] - fn test_with_negative_velocity() { - let mut obj = ThrowObject::new(Object { x: -10.0, y: 50.0 }, Object { x: -10.0, y: -10.0 }); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: -10.0, y: 50.0 }, - init_velocity: Object { x: -10.0, y: -10.0 }, - actual_position: Object { x: -20.0, y: 35.1 }, - actual_velocity: Object { x: -10.0, y: -19.8 }, - time: 1.0, - }) - ); - - assert_eq!( - obj.next(), - Some(ThrowObject { - init_position: Object { x: -10.0, y: 50.0 }, - init_velocity: Object { x: -10.0, y: -10.0 }, - actual_position: Object { x: -30.0, y: 10.4 }, - actual_velocity: Object { x: -10.0, y: -29.6 }, - time: 2.0, - }) - ); - - assert!(obj.next().is_none(), "{:?} instead of None", obj); - } - - #[test] - fn test_with_zero() { - let mut obj = ThrowObject::new(Object { x: 0.0, y: 0.0 }, Object { x: 0.0, y: 0.0 }); - - assert_eq!(obj.next(), None); - } -} diff --git a/tests/roman_numbers_iter_test/Cargo.toml b/tests/roman_numbers_iter_test/Cargo.toml index 256ac5b8..8af552f7 100644 --- a/tests/roman_numbers_iter_test/Cargo.toml +++ b/tests/roman_numbers_iter_test/Cargo.toml @@ -2,7 +2,7 @@ name = "roman_numbers_test" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/roman_numbers_iter_test/src/lib.rs b/tests/roman_numbers_iter_test/src/lib.rs new file mode 100644 index 00000000..499d9e0a --- /dev/null +++ b/tests/roman_numbers_iter_test/src/lib.rs @@ -0,0 +1,16 @@ +#[cfg(test)] +mod tests { + use roman_numbers_iter::*; + + #[test] + fn roman_numbers_iterator_test() { + let numbers = [0, 8, 5, 13, 33, 49, 199, 499, 1532, 2348]; + + for (n, e) in numbers.map(|n| (n, n + 1)) { + assert_eq!( + RomanNumber::from(n).next().unwrap().0, + RomanNumber::from(e).0, + ); + } + } +} diff --git a/tests/roman_numbers_iter_test/src/main.rs b/tests/roman_numbers_iter_test/src/main.rs deleted file mode 100644 index 9c32e2d2..00000000 --- a/tests/roman_numbers_iter_test/src/main.rs +++ /dev/null @@ -1,100 +0,0 @@ -// ## roman_numbers_iter - -// ### Instructions - -// Implement the `Iterator` trait for the `RomanNumber` type. You should use the code from the previous exercise roman_numbers. - -// ### Notions - -// - [Trait Iterator](https://doc.rust-lang.org/std/iter/trait.Iterator.html) - -// ### Expected Functions - -// ```rust -// //... - -// impl Iterator for RomanNumber {} -// ``` - -// ### Usage - -// Here is a program to test your function. - -// ```rust -// use roman_numbers::RomanNumber; - -// fn main() { -// let mut number = RomanNumber::from(15); - -// println!("{:?}", number); -// println!("{:?}", number.next()); -// } -// ``` - -// And its output - -// ```console -// $ cargo run -// RomanNumber([X, V]) -// Some(RomanNumber([X, V, I])) -// $ -// ``` - -pub use crate::RomanDigit::*; -use roman_numbers_iter::{RomanDigit, RomanNumber}; - -fn main() { - let mut number = RomanNumber::from(15); - - println!("{:?}", number); - println!("{:?}", number.next()); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn roman_numbers_iterator_test() { - assert_eq!( - RomanNumber::from(1).0, - RomanNumber::from(0).next().unwrap().0 - ); - assert_eq!( - RomanNumber::from(9).0, - RomanNumber::from(8).next().unwrap().0 - ); - assert_eq!( - RomanNumber::from(6).0, - RomanNumber::from(5).next().unwrap().0 - ); - assert_eq!( - RomanNumber::from(14).0, - RomanNumber::from(13).next().unwrap().0 - ); - assert_eq!( - RomanNumber::from(34).0, - RomanNumber::from(33).next().unwrap().0 - ); - assert_eq!( - RomanNumber::from(50).0, - RomanNumber::from(49).next().unwrap().0 - ); - assert_eq!( - RomanNumber::from(200).0, - RomanNumber::from(199).next().unwrap().0 - ); - assert_eq!( - RomanNumber::from(500).0, - RomanNumber::from(499).next().unwrap().0 - ); - assert_eq!( - RomanNumber::from(1533).0, - RomanNumber::from(1532).next().unwrap().0 - ); - assert_eq!( - RomanNumber::from(2349).0, - RomanNumber::from(2348).next().unwrap().0 - ); - } -} diff --git a/tests/sales_test/Cargo.toml b/tests/sales_test/Cargo.toml index 726de64c..9fd963eb 100644 --- a/tests/sales_test/Cargo.toml +++ b/tests/sales_test/Cargo.toml @@ -2,7 +2,7 @@ name = "sales_test" version = "0.1.0" authors = ["lee "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/sales_test/src/lib.rs b/tests/sales_test/src/lib.rs new file mode 100644 index 00000000..92c4d524 --- /dev/null +++ b/tests/sales_test/src/lib.rs @@ -0,0 +1,119 @@ +#[cfg(test)] +mod tests { + use sales::*; + + const STORE: Store<12> = Store::new([ + Item("product A", 1.23), + Item("product B", 23.1), + Item("product C", 3.12), + Item("product D", 9.75), + Item("product E", 1.75), + Item("product F", 23.75), + Item("product G", 2.75), + Item("product H", 1.64), + Item("product I", 15.23), + Item("product J", 2.10), + Item("product K", 54.91), + Item("product L", 43.99), + ]); + + #[test] + fn test_invalid_product() { + let mut cart = Cart::new(); + + assert_eq!(Err(()), cart.insert_item_by_name(&STORE, "product Z")); + } + + #[test] + fn test_empty_cart() { + let cart = Cart::new(); + + assert_eq!(cart.generate_prices(), []); + } + + #[test] + fn test_cart_one() { + let mut cart = Cart::new(); + + for p in ["product A", "product B", "product C"] { + cart.insert_item_by_name(&STORE, p).unwrap(); + } + + assert_eq!(cart.generate_prices(), [1.17, 2.98, 22.06]); + } + + #[test] + fn test_cart_two() { + let mut cart = Cart::new(); + + for p in [ + "product A", + "product B", + "product C", + "product D", + "product E", + "product F", + "product G", + ] { + cart.insert_item_by_name(&STORE, p).unwrap(); + } + + assert_eq!( + cart.generate_prices(), + [1.17, 1.67, 2.62, 2.98, 9.31, 22.05, 22.67] + ); + } + + #[test] + fn test_cart_three() { + let mut cart = Cart::new(); + + for p in [ + "product A", + "product B", + "product C", + "product D", + "product E", + "product F", + "product G", + "product H", + "product I", + ] { + cart.insert_item_by_name(&STORE, p).unwrap(); + } + + assert_eq!( + cart.generate_prices(), + [1.16, 1.55, 1.65, 2.6, 2.94, 9.2, 14.38, 21.8, 22.42] + ); + } + + #[test] + fn test_cart_four() { + let mut cart = Cart::new(); + + for p in [ + "product A", + "product B", + "product C", + "product D", + "product E", + "product F", + "product G", + "product H", + "product I", + "product J", + "product K", + "product L", + ] { + cart.insert_item_by_name(&STORE, p).unwrap(); + } + + assert_eq!( + cart.generate_prices(), + [ + 1.18, 1.58, 1.69, 2.02, 2.65, 3.01, 9.39, 14.67, 22.25, 22.88, 42.38, 52.9, + ] + ); + } +} diff --git a/tests/sales_test/src/main.rs b/tests/sales_test/src/main.rs deleted file mode 100644 index 581052ba..00000000 --- a/tests/sales_test/src/main.rs +++ /dev/null @@ -1,133 +0,0 @@ -use sales::*; - -fn main() { - let store = Store::new(vec![ - (String::from("product A"), 1.23), - (String::from("product B"), 23.1), - (String::from("product C"), 3.12), - ]); - - println!("{:?}", store); - // output: - // Store { products: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)] } - - let mut cart = Cart::new(); - cart.insert_item(&store, String::from("product A")); - cart.insert_item(&store, String::from("product B")); - cart.insert_item(&store, String::from("product C")); - - println!("{:?}", cart.generate_receipt()); - // output: - // [1.17, 2.98, 22.07] - - println!("{:?}", cart); - // output: - // Cart { items: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)], receipt: [1.17, 2.98, 22.07] } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[derive(Debug)] - struct Tests { - carts: Vec<(Cart, Vec)>, - } - - fn add_items(s: &Store, items: Vec<&str>, c: &mut Cart) { - for item in items.iter() { - c.insert_item(s, item.to_string()); - } - } - - impl Tests { - fn new() -> Tests { - let store = Store::new(vec![ - (String::from("product A"), 1.23), - (String::from("product B"), 23.1), - (String::from("product C"), 3.12), - (String::from("product D"), 9.75), - (String::from("product E"), 1.75), - (String::from("product F"), 23.75), - (String::from("product G"), 2.75), - (String::from("product H"), 1.64), - (String::from("product I"), 15.23), - (String::from("product J"), 2.10), - (String::from("product K"), 54.91), - (String::from("product L"), 43.99), - ]); - - let mut c = Cart::new(); - let mut c1 = Cart::new(); - let mut c2 = Cart::new(); - let mut c3 = Cart::new(); - add_items(&store, vec!["product A", "product B", "product C"], &mut c); - let sol = vec![1.17, 2.98, 22.06]; - add_items( - &store, - vec![ - "product A", - "product B", - "product C", - "product D", - "product E", - "product F", - "product G", - ], - &mut c1, - ); - let sol1 = vec![1.17, 1.67, 2.62, 2.98, 9.31, 22.05, 22.67]; - add_items( - &store, - vec![ - "product A", - "product B", - "product C", - "product D", - "product E", - "product F", - "product G", - "product H", - "product I", - ], - &mut c2, - ); - let sol2 = vec![1.16, 1.55, 1.65, 2.6, 2.94, 9.2, 14.38, 21.8, 22.42]; - add_items( - &store, - vec![ - "product A", - "product B", - "product C", - "product D", - "product E", - "product F", - "product G", - "product H", - "product I", - "product J", - "product K", - "product L", - ], - &mut c3, - ); - let sol3 = vec![ - 1.18, 1.58, 1.69, 2.02, 2.65, 3.01, 9.39, 14.67, 22.25, 22.88, 42.38, 52.9, - ]; - - Tests { - carts: vec![(c, sol), (c1, sol1), (c2, sol2), (c3, sol3)], - } - } - } - - #[test] - fn test_generate_receipt() { - let cases = Tests::new(); - - for (mut c, sol) in cases.carts.into_iter() { - assert_eq!(c.generate_receipt(), sol); - assert_eq!(c.receipt, sol); - } - } -} diff --git a/tests/slices_to_map_test/Cargo.toml b/tests/slices_to_map_test/Cargo.toml index d095219c..826b9dfb 100644 --- a/tests/slices_to_map_test/Cargo.toml +++ b/tests/slices_to_map_test/Cargo.toml @@ -2,7 +2,7 @@ name = "slices_to_map_test" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/slices_to_map_test/src/lib.rs b/tests/slices_to_map_test/src/lib.rs new file mode 100644 index 00000000..22bc8ac9 --- /dev/null +++ b/tests/slices_to_map_test/src/lib.rs @@ -0,0 +1,52 @@ +#[cfg(test)] +mod tests { + use slices_to_map::*; + use std::{collections::HashMap, sync::LazyLock}; + + static EXPECTED: LazyLock> = LazyLock::new(|| { + HashMap::from([ + ("Olivia", 1), + ("Liam", 3), + ("Emma", 23), + ("Noah", 5), + ("James", 2), + ]) + }); + + #[test] + fn test_same_length() { + assert_eq!( + slices_to_map( + &["Olivia", "Liam", "Emma", "Noah", "James"], + &[1, 3, 23, 5, 2] + ), + *EXPECTED + ); + } + + #[test] + fn test_different_length() { + let keys = ["Olivia", "Liam", "Emma", "Noah", "James"]; + let values = [1, 3, 23, 5, 2, 9]; + assert_eq!(slices_to_map(&keys, &values), *EXPECTED); + + let keys = ["Olivia", "Liam", "Emma", "Noah", "James", "Isabella"]; + let values = [1, 3, 23, 5, 2]; + assert_eq!(slices_to_map(&keys, &values), *EXPECTED); + } + + #[test] + fn it_works_for_vecs() { + let keys = ["Olivia", "Liam", "Emma", "Noah", "James"]; + let values = [1, 3, 23, 5, 2]; + assert_eq!(slices_to_map(&keys, &values), *EXPECTED); + + let keys = vec!["Olivia", "Liam", "Emma", "Noah", "James"]; + let values = vec![1, 3, 23, 5, 2, 9]; + assert_eq!(slices_to_map(&keys, &values), *EXPECTED); + + let keys = vec!["Olivia", "Liam", "Emma", "Noah", "James", "Isabella"]; + let values = vec![1, 3, 23, 5, 2]; + assert_eq!(slices_to_map(&keys, &values), *EXPECTED); + } +} diff --git a/tests/slices_to_map_test/src/main.rs b/tests/slices_to_map_test/src/main.rs deleted file mode 100644 index 958aca71..00000000 --- a/tests/slices_to_map_test/src/main.rs +++ /dev/null @@ -1,78 +0,0 @@ -// # Instructions: -// Create a function that borrows two slices (&[T]) and returns a hashmap where -// the first slice represents the keys and the second represents the values. - -// The signature of the function is the following -// fn slices_to_map<'a, T: Hash + Eq, U>(keys: &'a [T], values: &'a [U]) -> HashMap<&'a T, &'a U> { - -// # Example: -// for the slices &["hello", "how", "are", "you"] &[1, 3, 5, 8] -// returns the hashmap ["hello": 1, "how": 3, "are": 5, "you":8] - -use slices_to_map::*; -#[allow(unused_imports)] -use std::collections::HashMap; - -#[allow(dead_code)] -fn main() { - let keys = ["Olivia", "Liam", "Emma", "Noah", "James"]; - let values = [1, 3, 23, 5, 2]; - println!("{:?}", slices_to_map(&keys, &values)); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_same_length() { - let keys = ["Olivia", "Liam", "Emma", "Noah", "James"]; - let values = [1, 3, 23, 5, 2]; - let mut expected = HashMap::new(); - expected.insert(&"Olivia", &1); - expected.insert(&"Liam", &3); - expected.insert(&"Emma", &23); - expected.insert(&"Noah", &5); - expected.insert(&"James", &2); - assert_eq!(slices_to_map(&keys, &values), expected); - } - - #[test] - fn test_different_length() { - let keys = ["Olivia", "Liam", "Emma", "Noah", "James"]; - let values = [1, 3, 23, 5, 2, 9]; - let mut expected = HashMap::new(); - expected.insert(&"Olivia", &1); - expected.insert(&"Liam", &3); - expected.insert(&"Emma", &23); - expected.insert(&"Noah", &5); - expected.insert(&"James", &2); - assert_eq!(slices_to_map(&keys, &values), expected); - - let keys = ["Olivia", "Liam", "Emma", "Noah", "James", "Isabella"]; - let values = [1, 3, 23, 5, 2]; - assert_eq!(slices_to_map(&keys, &values), expected); - } - - #[test] - fn it_works_for_vecs() { - let mut expected = HashMap::new(); - expected.insert(&"Olivia", &1); - expected.insert(&"Liam", &3); - expected.insert(&"Emma", &23); - expected.insert(&"Noah", &5); - expected.insert(&"James", &2); - - let keys = ["Olivia", "Liam", "Emma", "Noah", "James"]; - let values = [1, 3, 23, 5, 2]; - - assert_eq!(slices_to_map(&keys, &values), expected); - let keys = vec!["Olivia", "Liam", "Emma", "Noah", "James"]; - let values = vec![1, 3, 23, 5, 2, 9]; - assert_eq!(slices_to_map(&keys, &values), expected); - - let keys = vec!["Olivia", "Liam", "Emma", "Noah", "James", "Isabella"]; - let values = vec![1, 3, 23, 5, 2]; - assert_eq!(slices_to_map(&keys, &values), expected); - } -} diff --git a/tests/step_iterator_test/Cargo.toml b/tests/step_iterator_test/Cargo.toml index d805de2f..b90f1675 100644 --- a/tests/step_iterator_test/Cargo.toml +++ b/tests/step_iterator_test/Cargo.toml @@ -2,7 +2,7 @@ name = "step_iterator_test" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/step_iterator_test/src/lib.rs b/tests/step_iterator_test/src/lib.rs new file mode 100644 index 00000000..f7a355c4 --- /dev/null +++ b/tests/step_iterator_test/src/lib.rs @@ -0,0 +1,32 @@ +#[cfg(test)] +mod tests { + use step_iterator::*; + + #[test] + fn test_next() { + let mut step_iterator = StepIterator::new(0, 100, 10); + assert_eq!(step_iterator.next(), Some(0)); + assert_eq!(step_iterator.next(), Some(10)); + } + + #[test] + fn until_the_end() { + for (i, v) in StepIterator::new(0, 100, 10).enumerate() { + assert_eq!(i * 10, v); + } + } + + #[test] + fn test_with_floats() { + for (i, v) in StepIterator::new(0.0, 10.0, 0.5).enumerate() { + assert_eq!(i as f64 * 0.5, v); + } + } + + #[test] + fn test_with_floats_with_imperfect_range() { + for (i, v) in StepIterator::new(0.3, 10.0, 0.5).enumerate() { + assert_eq!(i as f64 * 0.5 + 0.3, v); + } + } +} diff --git a/tests/step_iterator_test/src/main.rs b/tests/step_iterator_test/src/main.rs deleted file mode 100644 index 69caa81e..00000000 --- a/tests/step_iterator_test/src/main.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Create an Iterator (by implementing the std::iter::Iterator trait) -// that iterates through the values from beg to end (including end) in -// the indicated steps - -// The name of you're iterator will be StepIterator and it must be -// generic so you can use any integer value: i8,..,i64 of floating -// point number f32,..,f64 - -// Define the associated function: `new` that creates a new Step iterator: -// fn new(beg: T, end: T, step: T) -> StepIterator - -// For example: -// for v in StepIterator::new(0, 100, 10) { -// println!("{}", v); -// } -// must print: -// 0 -// 10 -// 20 -// 30 -// 40 -// 50 -// 60 -// 70 -// 80 -// 90 -// 100 - -// If the steps don't allow to arrive until the end of the sequence -// only the last value inferior than the end of the series will be returned -// Like beg: 0, end: 100, steps: 7 the last number returned will be -// the last number returned will be 98 - -use step_iterator::StepIterator; - -#[allow(dead_code)] -fn main() { - for v in StepIterator::new(0, 100, 10) { - print!("{},", v); - } - println!(); - - for v in StepIterator::new(0, 100, 12) { - print!("{},", v) - } - println!(); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_next() { - let mut step_iterator = StepIterator::new(0, 100, 10); - assert_eq!(step_iterator.next(), Some(0)); - assert_eq!(step_iterator.next(), Some(10)); - } - - #[test] - fn until_the_end() { - for (i, v) in StepIterator::new(0, 100, 10).enumerate() { - println!("position: {}, value: {}, ", i, v); - assert_eq!(i * 10, v); - } - } - - #[test] - fn test_with_floats() { - for (i, v) in StepIterator::new(0.0, 10.0, 0.5).enumerate() { - println!("position: {}, value: {}, ", i, v); - assert_eq!(i as f64 * 0.5, v); - } - } - - #[test] - fn test_with_floats_with_imperfect_range() { - for (i, v) in StepIterator::new(0.3, 10.0, 0.5).enumerate() { - println!("position: {}, value: {}, ", i, v); - assert_eq!(i as f64 * 0.5 + 0.3, v); - } - } -}