diff --git a/chapter-2/Cargo.lock b/chapter-2/Cargo.lock new file mode 100644 index 0000000..27f504b --- /dev/null +++ b/chapter-2/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "chapter-2" +version = "0.1.0" + diff --git a/chapter-2/Cargo.toml b/chapter-2/Cargo.toml new file mode 100644 index 0000000..02a8911 --- /dev/null +++ b/chapter-2/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "chapter-2" +version = "0.1.0" +authors = ["Vladan Popovic "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/chapter-2/src/main.rs b/chapter-2/src/main.rs new file mode 100644 index 0000000..8462c20 --- /dev/null +++ b/chapter-2/src/main.rs @@ -0,0 +1,72 @@ +use std::collections::HashMap; +use std::hash::Hash; +use std::time::Instant; + +fn memoize(f: F, mut store: HashMap) -> impl FnMut(A) -> B +where + F: Fn(A) -> B, +{ + move |x: A| { + let res = store.entry(x).or_insert_with(|| f(x)); + res.clone() + } +} + +fn fib(n: u64) -> u64 { + match n { + 0 => 1, + 1 => 1, + _ => fib(n - 1) + fib(n - 2), + } +} + +fn fibt(n: u64) -> u64 { + fn fib_tailrec(nt: u64, ct: u64, previous: u64, current: u64) -> u64 { + match ct { + 1 => fib_tailrec(nt, 2, 1, 1), + _ => { + if ct != nt { + fib_tailrec(nt, ct + 1, current, previous + current) + } else { + current + } + } + } + } + fib_tailrec(n + 1, 1, 0, 1) +} + +// mut f because of the mutable hash in memoize and hence the return FnMut +fn timeit(mut f: F) -> (T, u128) +where + F: FnMut() -> T, +{ + let now = Instant::now(); + let res = f(); + (res, now.elapsed().as_micros()) +} + +fn main() { + let mut mem_fib = memoize(fib, HashMap::new()); + let mut mem_fibt = memoize(fibt, HashMap::new()); + let (res, duration) = timeit(|| mem_fib(40)); + println!( + "Finished regular fib(40) = {} in {} microseconds", + res, duration + ); + let (res, duration) = timeit(|| mem_fib(40)); + println!( + "Finished memoized fib(40) = {} in {} microseconds", + res, duration + ); + let (res, duration) = timeit(|| mem_fibt(40)); + println!( + "Finished regular tailrec fib(40) = {} in {} microseconds", + res, duration + ); + let (res, duration) = timeit(|| mem_fibt(40)); + println!( + "Finished memoized tailrec fib(40) = {} in {} microseconds", + res, duration + ); +}