100-exercises-to-learn-rust
100-exercises-to-learn-rust copied to clipboard
Feedback: (06) ticket_management - (02) vec could lead to a much more complex problem
Hi, thanks for the exercices, I enjoy them.
In exercice (06) ticket_management - (02) vec, you have to complete the following function:
pub fn fibonacci(n: u32) -> u32 {
// TODO: implement the `fibonacci` function
//
// Hint: use a `Vec` to memoize the results you have already calculated
// so that you don't have to recalculate them several times.
todo!()
}
Following the hint, I used a vec to memoize the results in a vec, but my code ended up a tiny bit too complex with some once_cell::sync::Lazy and std::sync::Mutex, which doesn't seem right for such an exercice. I have done memoization in Rust before, and it's not super fun, so that could explain why I used once_cell stuff, but to me the hint was about caching the results between calls.
use once_cell::sync::Lazy;
use std::sync::Mutex;
static FIBONACCI_MEMO: Lazy<Mutex<Vec<u32>>> = Lazy::new(|| Mutex::new(vec![0, 1]));
pub fn fibonacci(n: u32) -> u32 {
let nusize = n as usize;
let mut memo = FIBONACCI_MEMO.lock().unwrap();
if memo.len() <= nusize {
if memo.capacity() <= nusize {
memo.reserve(nusize * 2);
}
std::mem::drop(memo);
let result = fibonacci(n - 2) + fibonacci(n - 1);
let mut memo = FIBONACCI_MEMO.lock().unwrap();
memo.push(result);
return result;
}
memo[nusize]
}
I looked at the solution and I see that it's much simpler.
pub fn fibonacci(n: u32) -> u32 {
let n = n as usize;
let mut memo = vec![0, 1];
for i in 2..=n {
memo.push(memo[i - 1] + memo[i - 2]);
}
memo[n]
}
But I'm not sure the Vec is necessary at all:
pub fn fibonacci(n: u32) -> u32 {
if n <= 1 {
return n;
}
let mut a = 0;
let mut b = 1;
for _ in 2..=n {
let c = a + b;
a = b;
b = c;
}
b
}