diff --git a/exercises/18_iterators/iterators4.rs b/exercises/18_iterators/iterators4.rs index ae4d502d..08ba3650 100644 --- a/exercises/18_iterators/iterators4.rs +++ b/exercises/18_iterators/iterators4.rs @@ -1,9 +1,9 @@ -fn factorial(num: u64) -> u64 { - // Complete this function to return the factorial of num +fn factorial(num: u8) -> u64 { + // TODO: Complete this function to return the factorial of `num`. // Do not use: // - early returns (using the `return` keyword explicitly) // Try not to use: - // - imperative style loops (for, while) + // - imperative style loops (for/while) // - additional variables // For an extra challenge, don't use: // - recursion @@ -19,20 +19,20 @@ mod tests { #[test] fn factorial_of_0() { - assert_eq!(1, factorial(0)); + assert_eq!(factorial(0), 1); } #[test] fn factorial_of_1() { - assert_eq!(1, factorial(1)); + assert_eq!(factorial(1), 1); } #[test] fn factorial_of_2() { - assert_eq!(2, factorial(2)); + assert_eq!(factorial(2), 2); } #[test] fn factorial_of_4() { - assert_eq!(24, factorial(4)); + assert_eq!(factorial(4), 24); } } diff --git a/rustlings-macros/info.toml b/rustlings-macros/info.toml index 8b1feb49..72f956bf 100644 --- a/rustlings-macros/info.toml +++ b/rustlings-macros/info.toml @@ -942,10 +942,10 @@ dir = "18_iterators" hint = """ In an imperative language, you might write a `for` loop that updates a mutable variable. Or, you might write code utilizing recursion and a match clause. In -Rust you can take another functional approach, computing the factorial +Rust, you can take another functional approach, computing the factorial elegantly with ranges and iterators. -Hint 2: Check out the `fold` and `rfold` methods!""" +Check out the `fold` and `rfold` methods!""" [[exercises]] name = "iterators5" diff --git a/solutions/18_iterators/iterators4.rs b/solutions/18_iterators/iterators4.rs index 4e181989..4c3c49d9 100644 --- a/solutions/18_iterators/iterators4.rs +++ b/solutions/18_iterators/iterators4.rs @@ -1 +1,71 @@ -// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 +// 3 possible solutions are presented. + +// With `for` loop and a mutable variable. +fn factorial_for(num: u64) -> u64 { + let mut result = 1; + + for x in 2..=num { + result *= x; + } + + result +} + +// Equivalent to `factorial_for` but shorter and without a `for` loop and +// mutable variables. +fn factorial_fold(num: u64) -> u64 { + // Case num==0: The iterator 2..=0 is empty + // -> The initial value of `fold` is returned which is 1. + // Case num==1: The iterator 2..=1 is also empty + // -> The initial value 1 is returned. + // Case num==2: The iterator 2..=2 contains one element + // -> The initial value 1 is multiplied by 2 and the result + // is returned. + // Case num==3: The iterator 2..=3 contains 2 elements + // -> 1 * 2 is calculated, then the result 2 is multiplied by + // the second element 3 so the result 6 is returned. + // And so on… + (2..=num).fold(1, |acc, x| acc * x) +} + +// Equivalent to `factorial_fold` but with a built-in method that is suggested +// by Clippy. +fn factorial_product(num: u64) -> u64 { + (2..=num).product() +} + +fn main() { + // You can optionally experiment here. +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn factorial_of_0() { + assert_eq!(factorial_for(0), 1); + assert_eq!(factorial_fold(0), 1); + assert_eq!(factorial_product(0), 1); + } + + #[test] + fn factorial_of_1() { + assert_eq!(factorial_for(1), 1); + assert_eq!(factorial_fold(1), 1); + assert_eq!(factorial_product(1), 1); + } + #[test] + fn factorial_of_2() { + assert_eq!(factorial_for(2), 2); + assert_eq!(factorial_fold(2), 2); + assert_eq!(factorial_product(2), 2); + } + + #[test] + fn factorial_of_4() { + assert_eq!(factorial_for(4), 24); + assert_eq!(factorial_fold(4), 24); + assert_eq!(factorial_product(4), 24); + } +}