taro
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
Marked As Solved
100phlecs
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)
Also Liked
Adzz
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







