# FizzBuzz in recursion?

I’m overthinking FizzBuzz in Elixir, refactoring everything possible Elixir way.

Now I’m trying to find a recursive way to put an IO list together so it will result in `["Fizz", ["Buzz"]]`. But I’m quite stuck, recursion is difficult to grasp. So I’ve decided to ask smarter people.

``````defmodule FizzBuzz do
...

def change(num) do
# Recurse in with an integer in closure
# Recurse out leaving string each step
end

defp name_multiple(num) when rem(num, 3) == 0, do: "Fizz"
defp name_multiple(num) when rem(num, 5) == 0, do: "Buzz"
defp name_multiple(_), do: ""
end
``````

I’m not asking for the simpler solutions of FizzBuzz. I want to join FizzBuzz instead of returning them separately, so it’s more extensible. I also tried to use multi-clause functions and guards as much as I can.

My previous solution is

``````defmodule FizzBuzz do
@moduledoc """
Name multiples.

* Multiples of 3 => "Fizz"
* Multiples of 5 => "Buzz"

Concatenates when many are applicable.

* Multiples of 3 and 5 => "FizzBuzz"

Unapplicable numbers remain intact.
"""

@spec list(integer) :: list
def list(max) when is_integer(max), do: list(1..max)

@spec list(Enumerable.t()) :: list
def list(enum), do: Enum.map(enum, &change/1)

@spec change(integer) :: integer | String.t()
def change(num) do
num
|> prefer(fizz(num))
|> prefer(buzz(num))
end

defp prefer(old, new) when not new, do: old
defp prefer(old, new) when not is_binary(old), do: new
defp prefer(old, new), do: old <> new

defp fizz(num) when rem(num, 3) == 0, do: "Fizz"
defp fizz(_), do: false

defp buzz(num) when rem(num, 5) == 0, do: "Buzz"
defp buzz(_), do: false
end``````

So the thing with recursion is you first want to ensure you know the conditions under which you want to stop recuring.

In this case that’s not clear, but I assume you want to halt once you have reached some maximum number of iterations. So let’s first call a recursive function, but implement the break condition:

``````defmodule FizBuzz do
def change(max) do
change(max, [], max - 1)
end

def change(_number, result, iterations) when iterations == 0 do
result
end
end
``````

If we call it like this `FizzBuzz.change(0)` we will be returned `[]`.

Now we can add the other conditions

``````defmodule FizBuzz do
def change(max) do
change(max, [], max)
end

def change(number, result, iterations) when iterations <= 0 do
result
end

def change(number, result, iterations) when rem(number, 15) == 0 do
change(number - 1, ["FizzBuzz" | result], iterations - 1)
end

def change(number, result, iterations) when rem(number, 5) == 0 do
change(number - 1, ["Buzz" | result], iterations - 1)
end

def change(number, result, iterations) when rem(number, 3) == 0 do
change(number - 1, ["Fizz" | result], iterations - 1)
end

def change(number, result, iterations) do
change(number - 1, [number | result], iterations - 1)
end
end
``````
1 Like

I want to join FizzBuzz instead of returning them separately, so it’s more extensible

Here’s what I came up with.

``````defmodule FizzBuzz do
def convert(num, lst \\ [])
def convert(num, lst) when rem(num, 5) == 0, do: num |> extract(5) |> convert(["Buzz" | lst])
def convert(num, lst) when rem(num, 3) == 0, do: num |> extract(3) |> convert(["Fizz" | lst])
def convert(_num, lst) when length(lst) > 0, do: lst
def convert(num, _lst), do: num

defp extract(num, factor) when rem(num, factor) == 0, do: num |> div(factor) |> extract(factor)
defp extract(num, _factor), do: num
end

maybe_join = fn
elem when is_list(elem) -> Enum.join(elem)
num when is_integer(num) -> num
end

1..100
|> Enum.map(&FizzBuzz.convert/1)
|> Enum.map(maybe_join)
``````
1 Like