Fizzbuzz In Elixir by Daniel Jaouen

2017-11-27

Today, we’re going to examine how to implement a common interview question’s code in Elixir: fizzbuzz. We’ll start out by implementing a GenServer to handle the application logic for us:

defmodule Fizzbuzz.Worker do
  use GenServer

  def start_link do
    GenServer.start_link(__MODULE__, [])
  end

  def call(pid, n) do
    GenServer.call(pid, {:get, n})
  end

  def init([]) do
    {:ok, %{}}
  end

  def handle_call({:get, n}, _from, _state) do
    reply = cond do
      rem(n, 15) == 0 ->
        "fizzbuzz"
      rem(n, 3) == 0 ->
        "fizz"
      rem(n, 5) == 0 ->
        "buzz"
      true ->
        n
    end

    {:reply, reply, %{}}
  end
end

We see here that we have a basic GenServer set up with a handle_call that checks for the appropriate conditions to print out fizz, buzz, or fizzbuzz. Note that we don’t need state here, so our return value has an empty map in it.

Now fire up IEx (iex -S mix in the project directory). Our general approach is as follows:

  1. Create 20 pids of our GenServer with a for loop.
  2. Create 20 tasks, each one with a function passed in that calls our GenServer API.
  3. Call Task.await on our tasks.

You can see this implemented in the following code:

iex(1)> pids = for i <- 0..19 do
...(1)>   {:ok, pid} = Fizzbuzz.Worker.start_link
...(1)>   pid
...(1)> end
[#PID<0.134.0>, #PID<0.135.0>, #PID<0.136.0>, #PID<0.137.0>, #PID<0.138.0>,

 *snip*

 #PID<0.149.0>, #PID<0.150.0>, #PID<0.151.0>, #PID<0.152.0>, #PID<0.153.0>]
iex(2)> tasks = for i <- 0..19 do
...(2)>   pid = Enum.at(pids, i)
...(2)>   Task.async fn -> Fizzbuzz.Worker.call(pid, i + 1) end
...(2)> end
[%Task{owner: #PID<0.125.0>, pid: #PID<0.158.0>,
  ref: #Reference<0.4242417377.455081986.187387>},

 *snip*

 %Task{owner: #PID<0.125.0>, pid: #PID<0.177.0>,
  ref: #Reference<0.4242417377.455081985.188134>}]
iex(3)> for i <- 0..19 do
...(3)>   Enum.at(tasks, i) |> Task.await
...(3)> end
[1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14,
 fizzbuzz, 16, 17, fizz, 19, buzz]

And it works! Feel free to leave a comment if you found this informative or useful.

Comment

Back