Chapter 2 exercises: memoize fib and timeit
This commit is contained in:
parent
c6c48de95f
commit
54df888af7
3 changed files with 87 additions and 0 deletions
6
chapter-2/Cargo.lock
generated
Normal file
6
chapter-2/Cargo.lock
generated
Normal file
|
@ -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"
|
||||||
|
|
9
chapter-2/Cargo.toml
Normal file
9
chapter-2/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "chapter-2"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Vladan Popovic <vladanovic@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
72
chapter-2/src/main.rs
Normal file
72
chapter-2/src/main.rs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::hash::Hash;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
fn memoize<A: Copy + Hash + Eq, B: Clone, F>(f: F, mut store: HashMap<A, B>) -> 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<T, F>(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
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in a new issue