7 Lines to Code Fizz-Buzz Game Principle in Elixir

Coding FizzBuzz Game Backend Principles

Photo by Jaciel Melnik on Unsplash

This article is all about coding the implicit conditions in FizzBuzz. This makes you to walk over lines of code that gives similar output with different syntax.

To whom ?

This is for complete beginners in Elixir. But, this gonna be more informative at the end.

What is Fizz-Buzz ?

When you google, you will find the following phrases about the FizzBuzz.

FizzBuzz is a very simple programming task, used in software developer job interviews, to determine whether the job candidate can actually write code.

Fizz buzz is a group word game for children to teach them about division. Players take turns to count incrementally, replacing any number divisible by three with the word “fizz”, and any number divisible by five with the word “buzz” and if divisible by both three and five with the word FizzBuzz or else just printing the number itself.

That’s all about the FizzBuzz. Oh.. you finally know what FizzBuzz is . Keep Rocking…

What are we gonna code here?

We simply print the numbers in a range replacing them with words Fizz, Buzz, and FizzBuzz using game protocol.

Fizz-Buzz Timeline

Time to code…

Fizz Section

Here, I named the module with FizzBuzz of course everybody does the same and wrote a play/2 function.

At first we just print the numbers in the range and see how it works.

defmodule FizzBuzz do
def play(min, max) do
Enum.each(min..max, fn(num)-> IO.puts num end )
end
end

play/2

This function takes two numbers as input technically minimum and maximum values in a range. So, we can create a range via ../2 macro.

min..max

A range is represented internally as a struct. A range implements the Enumerable protocol, which means functions in the Enum module can be used to work with ranges.

You can check the implemented protocols with the help of i/1

i 1..2
i 1..2

So, we took the help of each function in the Enum module to iterate a function over the range and printing the numbers.

fn(num) -> IO.puts num end

Here, we used the anonymous function to print the numbers by calling IO.puts inside the function.

Pattern Matching over function input values

Here, we will write another function with the same name play but, this time it takes only single input play/1 . According to OOP it is called as Method Overloading.

This is how the code looks.

defmodule FizzBuzz do
def play(min, max) do
Enum.each(min..max, fn(num)-> play(num) end )
end
  def play(num) when rem(num, 3) == 0 do
IO.puts "Fizz"
end
end

Changes:

Instead of calling the IO.puts inside the anonymous function, we created a function for printing. Here, inside the function definition of play/1 , we took the help of Elixir guard clause when to meet the game conditions.

If the number is divisible by three, the remainder will be 0 . So, we are using the rem/2 function to get the remainder and == to check the truth value of the expression. If the truth value is true , it runs the function definition otherwise it won’t run the definition.

Now copy the code and paste it inside the iex. It compiles well.

Now, call the play function as

iex> FizzBuzz.play 1,20

You will see the run time error. It compiled well but, we got an error at run time.

This is how the error looks.

Trouble Shooting

What’s wrong with our code ?

The first value in the range 1..20 will be 1 because, ranges are always inclusive.

The first iteration of function call will look like

Enum.each -- 
fn(1)-> play(1) end

Here,play function is triggered with a value 1 but, the guard clause expression rem(1, 3)==0 would results to false So, the function clause is not matched with the passed value.

So, we need to write another print function to take charge of printing numbers that don’t divisible by 3 and this is how the code looks.

defmodule FizzBuzz do
  def play(min, max) do 
Enum.each(min..max, fn(num)-> play(num) end )
end
  def play(num) when rem(num, 3) == 0 do
IO.puts "Fizz"
end
  def play(num) do
IO.puts num
end
end

Now give a try by copy pasting above lines of code inside iex and call the play function as FizzBuzz.play 1,20.

You will see the numbers divisible by three iterations will print Fizz instead of printing number.

Buzz Section

Like Fizz, we have to add another function play/1 function with guard clause checking for divisibility with 5.

Lets see the updated code

defmodule FizzBuzz do
  def play(min, max) do 
Enum.each(min..max, fn(num)-> play(num) end )
end
  def play(num) when rem(num, 3) == 0 do
IO.puts "Fizz"
end
 def play(num) when rem(num, 5) == 0 do
IO.puts "Buzz"
end
  def play(num) do
IO.puts num
end
end

FizzBuzz Section

Like Fizz and Buzz we can check the number divisibility by 3 and 5 considering LCM (least common multiple ) of both numbers. The LCM of 3 and 5 is 15. So, if number is divisible by 15, then it is divisible by both 3 and 5.

Let’s add another function.

defmodule FizzBuzz do
  def play(min, max) do 
Enum.each(min..max, fn(num)-> play(num) end )
end
  def play(num) when rem(num, 3) == 0 do
IO.puts "Fizz"
end
  def play(num) when rem(num, 5) == 0 do
IO.puts "Buzz"
end
  def play(num) when rem(num, 15) == 0 do
IO.puts "FizzBuzz"
end
  def play(num) do
IO.puts num
end
end

Now copy and paste above lines of code and run the play/2 function.

To our surprise, it prints the Fizz instead of FizzBuzz at iteration 15.

What’s wrong with our code ?

Trouble Shooting

defmodule FizzBuzz do
def play(min, max) do 
Enum.each(min..max, fn(num)-> play(num) end )
end
def play(num) when rem(num, 3) == 0 do
IO.puts "Fizz"
end
def play(num) when rem(num, 5) == 0 do
IO.puts "Buzz"
end
def play(num) when rem(num, 15) == 0 do
IO.puts "FizzBuzz"
end
def play(num) do
IO.puts num
end
end

Let’s interpret the code at 15 iteration

Enum.each -- #15
play(15)
--
play(15) when rem(15, 3) == 0 do

The expression rem(15, 3)==0would results to true . So, it is just printing the Fizz and jumping to next iteration.

So, we need to re order our functions. The play/1 function with a guard clause rem(num, 15) == 0 should be above the all the remaining functions. So, it first checks the divisibility with 15 then with 3 and then with 5.

Let’s update the code.

defmodule FizzBuzz do
def play(min, max) do 
Enum.each(min..max, fn(num)-> play(num) end )
end
def play(num) when rem(num, 15) == 0 do
IO.puts "FizzBuzz"
end
def play(num) when rem(num, 3) == 0 do
IO.puts "Fizz"
end
def play(num) when rem(num, 5) == 0 do
IO.puts "Buzz"
end
def play(num) when rem(num, 15) == 0 do
IO.puts "FizzBuzz"
end
def play(num) do
IO.puts num
end
end

Now copy and paste above lines of code in iex and run the FizzBuzz.play 1, 20 function.

Hurray! We finished the code logic.

But, the title of the article says we need to do that in seven (7) lines of code.

Let’s improve our code.

What else we can improve ?

Instead of copy pasting into iex every time, we can create a file fizz_buzz.ex and paste the code into it.

file fizz_buzz.ex

Now run the command

iex fizz_buzz.ex

You have to be in the same directory of where the file exists.

Otherwise you have to run the command as

iex path/to/file/fizz_buzz.ex

It loads the module into your new iex session. You can still check the whether the module is loaded with Code.ensure_loaded FizzBuzz

The changes in the file fizz_buzz.ex , can be recompiled with r FizzBuzz . Here r recompiles and reloads the given module.

Code Improvement.

So far, our code consists of 20 lines after deleting empty new lines.

Now we have to improve our code to look much better than before.

Replacements

In elixir, we can replace anonymous function fn(num)-> play(num) endwith &(play(&1))

So update the line

to

Save the file and recompile it with r fizz_buzz.ex

We can make this more simple by just passing the name of the function with arity to iterate over the range in each

So, update line

Enum.each(min..max, &(play(&1)))

to

Enum.each(min..max, &play/1)

Now save the file with updates then recompile and test it. It still works.

Single Line Functions in Elixir

If you clearly observe the code logic, most of our function definitions are one line. So, we can avoid the do .. end blocks. We can update our function definitions with do: single line style.

#before
def play(num) when rem(num, 15) == 0 do
IO.puts "FizzBuzz"
end
#after updating
def play(num, 3) when rem(num, 3) == 0, do: IO.puts "FizzBuzz"

Similarly, we will update the remaining function definitions with single line style code base.

This is how it looks after updating

defmodule FizzBuzz do
def play(min, max), do: Enum.each(min..max, &play/1)
def play(num) when rem(num, 15) == 0, do: IO.puts "FizzBuzz"
def play(num) when rem(num, 3) == 0, do: IO.puts "Fizz"
def play(num) when rem(num, 5) == 0, do: IO.puts "Buzz"
def play(num), do: IO.puts num
end

Boom! We developed code logic in 7 lines. That was awesome of you…

This article originally posted at Ahamtech Blog

Happy Coding…

if worth_clapping, do: “clap”, else: nil
Like what you read? Give Blackode a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.