diff --git a/Rust/Cargo.lock b/Rust/Cargo.lock new file mode 100644 index 0000000..fd62ef1 --- /dev/null +++ b/Rust/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "factorialFinder" +version = "0.1.0" diff --git a/Rust/Cargo.toml b/Rust/Cargo.toml new file mode 100644 index 0000000..098d00f --- /dev/null +++ b/Rust/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "factorialFinder" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/Rust/README.md b/Rust/README.md new file mode 100644 index 0000000..64870f6 --- /dev/null +++ b/Rust/README.md @@ -0,0 +1,64 @@ +# Factorial Finder in Rust +In this code challenge we write a program that finds the factorial of a positive integer in the Rust programming language. + +## Problem +The Factorial of a positive integer, n, is defined as the product of the sequence n, n-1, n-2, ...1 and the factorial of zeo, 0, is defined as being 1. Solve this using both loops and recursion. + +## Solution +As the problem specifies we are trying to find the factorial of a positive integer. +A factorial is the product of all numbers between n and 0. For example, if n is 10 then the factorial of n would be 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x 1 = 3628800. +The challenge also states we must solve it using both loops and recursion. + +### Solving the factorial with loops +Rust has different kinds of looping but the best kind of loop for our situation is a `while` loop. +This loops lets us check if a condition is true to break the loop, in our case, we check if `f` is above `1`. +1. Create a function that takes the mutable i64 parameter `f` and returns an 64-bit integer. +2. loop until `f` is `0` or below + 1. multiply the sum (default to 1) by `f` + 2. subtract `f` by `1` (decreasing the count until `f` is 0) +3. Return the sum +This simulates the process of factorial by multiplying the sum by every digit between `f` and `0`. +```rust +// Simple looping algorithm +fn factorial_loop(mut f: i64) -> i64 { + // sum is 1 so if f is 0 the function returns 1 + let mut sum: i64 = 1; + + // Multiplying the sum by f and subtracting f by 1 every loop + while f > 0 { + sum *= f; + f -= 1; + } + + return sum; +} +``` + +### Solving the factorial with recursion +Using recursion can make our code shorter and easier to understand. In this technique, we call the function within it's self usually with altered arguments. +1. Create a function that takes the mutable i64 parameter `f` and returns an 64-bit integer. +2. if `f` is 0 or below 0 we return 1 +3. otherwise we return `f` multiplied by the function by with `f` reduced by 1 +```rust +// Recursive algorithm +fn factorial_recursion(f: i64) -> i64 { + // Return 1 if f is 0 otherwise we multiply the current f by + // the result of our current function f-1 + return if f <= 0 { 1 } else { f * factorial_recursion(f-1) } +} +``` + +## Benchmarking +Rust is a systems programming language and therefore runs this code with exceptional speed. +The looping function completed in roughly **6-8 microseconds** to calculate the factorial 10, +and recursion completed in **0-1 microseconds** to calculate the same. +Rust has several optimisations which makes recursion faster in this scenario. + +The benchmarking function used is provided below: +```rust +fn benchmark(f: fn(i64) -> i64, arg: String) -> (i64, Duration) { + let now = Instant::now(); + let loop_result: i64 = f(arg.trim().parse::().unwrap()); + return (loop_result, now.elapsed()); +} +``` diff --git a/Rust/src/main.rs b/Rust/src/main.rs new file mode 100644 index 0000000..5c8c05a --- /dev/null +++ b/Rust/src/main.rs @@ -0,0 +1,52 @@ +use std::io; +use std::time::{Duration, Instant}; // NOTE: This is only used for benchmarking + +// Simple looping algorithm +fn factorial_loop(mut f: i64) -> i64 { + // sum is 1 so if f is 0 the function returns 1 + let mut sum: i64 = 1; + + // Multiplying the sum by f and subtracting f by 1 every loop + while f > 0 { + sum *= f; + f -= 1; + } + + return sum; +} + +// Recursive algorithm +fn factorial_recursion(f: i64) -> i64 { + // Return 1 if f is 0 otherwise we multiply the current f by + // the result of our current function f-1 + return if f <= 0 { 1 } else { f * factorial_recursion(f-1) } +} + +fn main() { + println!("Factorial Finder in Rust!"); + println!("Please enter a number: "); + + // Getting input from command line + let mut input = String::new(); + io::stdin() + .read_line(&mut input) + .expect("An error occurred while getting user input"); + + // We get the result from the calculation and the duration it took + let loop_result = benchmark(factorial_loop, input.clone()); + let recursion_result = benchmark(factorial_recursion, input.clone()); + + // Display results to user + println!("Factorial of {} is {}!", input.trim(), loop_result.0); + println!("Using loops it took {} microseconds!", loop_result.1.as_micros()); + println!("Using recursion it took {} microseconds!", recursion_result.1.as_micros()); +} + +// Function used to benchmark +// This functional only calculates the duration and calls either +// loop or recursion depending on the function we provide it +fn benchmark(f: fn(i64) -> i64, arg: String) -> (i64, Duration) { + let now = Instant::now(); + let loop_result: i64 = f(arg.trim().parse::().unwrap()); + return (loop_result, now.elapsed()); +}