taro

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

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

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

Where Next?

Popular in Questions Top

JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

Other popular topics Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

We're in Beta

About us Mission Statement