Skip to content

Instantly share code, notes, and snippets.

@kyanny
Created March 13, 2012 01:27
Show Gist options
  • Save kyanny/2026028 to your computer and use it in GitHub Desktop.
Save kyanny/2026028 to your computer and use it in GitHub Desktop.
Elixir fibonacci #1
defmodule Fib do
def fib(0) do 0 end
def fib(1) do 1 end
def fib(n) do fib(n-1) + fib(n-2) end
end
IO.puts Fib.fib(10)
@ChristopheBelpaire
Copy link

This one is tail call optimized :)

defmodule Fib do
  def fib(a, _, 0 ) do a end

  def fib(a, b, n) do fib(b, a+b, n-1) end

end
IO.puts Fib.fib(1,1,6)

Copy link

ghost commented Feb 15, 2016

defmodule Fib do
defp fib(0) do 0 end
defp fib(1) do 1 end
defp fib(n) when n>=0 do
fib(n-1) + fib(n-2)
end
def fibo(x) do
for n<-0..x-1 , do: fib(n)
end
end
Output:
iex(1)>Fib.fibo(4)
[0, 1, 1, 2]

@simonneutert
Copy link

simonneutert commented Mar 13, 2017

An idiomatic take on this topic :)

defmodule Fib do
    def fib(a, b, n) do
        case n do
            0 ->
                a
            _ ->
                fib(b, a+b, n-1)
        end
    end
end
# Console Output
IO.puts Fib.fib(1,1,7)

@dhc02
Copy link

dhc02 commented Sep 19, 2018

Another approach that returns the entire sequence as a list.

defmodule Fibonacci do
  def find(nth) do
    list = [1, 1]
    fib(list, nth)
  end

  def fib(list, 2) do
    Enum.reverse(list)
  end

  def fib(list, n) do
    fib([hd(list) + hd(tl(list))] ++ list, n - 1)
  end
end

Usage:

> find 7
[1, 1, 2, 3, 5, 8, 13]

@kanmaniselvan
Copy link

A little optimization to @dhc02's approach, which removes ++ operation to list as it's less performant and uses pattern matching for finding the first two elements of the list.

defmodule Fibonacci do
  def find(nth) do
    list = [1, 1]
    fib(list, nth)
  end

  def fib(list, 2) do
    Enum.reverse(list)
  end

  def fib(list, n) do
    [first_elem, second_elem | _] = list
    fib([first_elem + second_elem | list], n - 1)
  end
end

@luizdamim
Copy link

luizdamim commented Jan 14, 2021

My two takes using dynamic programming:

defmodule FibDynamicProgramming do
  def fib(n) do
    cache = %{0 => 0, 1 => 1}

    cache =
      Enum.reduce(2..n, cache, fn
        i, acc ->
          Map.put(acc, i, acc[i-2] + acc[i-1])
      end)

    cache[n]
  end
end

IO.inspect(FibDynamicProgramming.fib(10))
55
defmodule FibDynamicProgrammingAgent do
  use Agent

  def start_link(_) do
    Agent.start_link(fn -> %{} end, name: __MODULE__)
  end

  def fib(n) do
    put(0, 0)
    put(1, 1)

    for i <- 2..n do
      put(i, get(i-2) + get(i-1))
    end

    get(n)
  end

  defp get(n), do: Agent.get(__MODULE__, fn state -> state[n] end)

  defp put(n, val), do: Agent.update(__MODULE__, fn state -> Map.put(state, n, val) end)
end

FibDynamicProgrammingAgent.start_link(nil)
IO.inspect(FibDynamicProgrammingAgent.fib(10))
55

@edoardocostantinidev
Copy link

My take on the issue, heavily inspired by @luizdamim:

defmodule Fibonacci.Map do
    def compute(n) do
      compute(2, n, %{0 => 0, 1 => 1})
    end

    def compute(n, target, map) when n == target do
      map[n - 1] + map[n - 2]
    end

    def compute(n, target, map) do
      value = map[n - 1] + map[n - 2]
      newMap = Map.put(map, n, value)
      compute(n + 1, target, newMap)
    end
  end

@YesIIBr0
Copy link

@edoardocostantinidev in your examples, does Map function works as same in python or c++? i never try Elixir and im learning from scratch.

@edoardocostantinidev
Copy link

@YesIIBr0 Map in this case is data structure that in elixir is documented by this page. Is basically a key-value store

@ermanimer
Copy link

ermanimer commented Jul 26, 2023

My take with tail call optimization:

defmodule Fibonacci do
  def nth(n) when n <= 1, do: n

  def nth(n) do
    fib(n - 2, 1, 0)
  end

  defp fib(0, minus_1, minus_2) do
    minus_1 + minus_2
  end

  defp fib(n, minus_1, minus_2) do
    fib(n - 1, minus_1 + minus_2, minus_1)
  end
end

@pmarreck
Copy link

I'd never put my version in lol

#!/usr/bin/env elixir

defmodule Fibonacci do
  def nth([n]) when is_binary(n), do: nth(String.to_integer(n)) 
  def nth(n) when n < 1, do: {:error, :undefined}
  def nth(1), do: 0
  def nth(n), do: nth(1, 0, n - 2)
  def nth(last, _last_last, 0), do: last
  def nth(last, last_last, current), do: nth(last + last_last, last, current - 1)
end

# inline "tests"
0 = Fibonacci.nth(1)
2 = Fibonacci.nth(4)
21 = Fibonacci.nth(9)

IO.puts Fibonacci.nth(System.argv())

@Lawrence-2001
Copy link

Lawrence-2001 commented Aug 1, 2023

defmodule Fibonacci do
  def find(n) do
    list = [1, 0]
    fib(list, n)
  end
  
  def fib(_list, n) when n < 0 do
    []
  end

  def fib(_list, 0) do
    [0]
  end

  def fib(list, 1) do
    list
  end

  def fib(list, n) do
    [first_elem, second_elem | _] = list
    fib([first_elem + second_elem | list], n - 1)
  end
end

10 |> Fibonacci.find() |> IO.inspect()

@Lawrence-2001
Copy link

Lawrence-2001 commented Aug 1, 2023

defmodule Fib do
    def run(a, b, n) do
        case n do
            1 ->
                b
            _ ->
                run(b, a + b, n - 1)
        end
    end
end

Fib.run(0,1,10) |> IO.puts()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment