If you're up for a challenge…
The classic Fibonacci implementation is
def fib(0), 0
def fib(1), 1
def fib(n), fib(n-1) + fib(n-2)
This has a worst case performance of \( O( 1.6^{n+1} ) \). For large \( n \), this is a big number (20 digits or so long for \( n = 100 \)). This means it is slow, and it burns through stack space at an alarming rate.
However, you can make the function perform in linear time by
implementing a simple cache. An Elixir map is a good data structure
for this. Initialize it with %{ 0 => 0, 1 => 1 }
, and add new values
to it as you discover them.
Write a module that implements the cache. It should use an agent, and that agent's state should be the map.
Then write a Fibonacci module that uses this cache.
Try calculating fib(100)
. If it comes back without crashing your
machine, and before the sun has expanded to consume the Earth, then
your cache worked...
I like @pragdave' s solution, the Agent/Cache is completely hidden from the user.
However, he uses a custom made (and dare I say an also more complicated) cache. (The function name complete_if_not_found is somewhat confusing, the second and last implementation of complete_if_not_found is doing the opposite which is nothing because the value was found!)
Why not use a 'standard Map cache', used in the Agent example in the getting started guide from elixir-lang.org ( see the example pf KV.Bucket ) and combine this with @fahrinh's Fib implementation?
Usage:
PS: In this case I find the usage of a good old if statement more acceptable than an implementation like below: