Coding FizzBuzz Game Backend Principles
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.
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.
1
2
3
4
5
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
1
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.
1
2
3
4
5
6
7
8
9
10
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
1
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
1
2
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.
1
2
3
4
5
6
7
8
9
10
11
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
1
2
3
4
Enum.each -- #15
play(15)
--
play(15) when rem(15, 3) == 0 do
The expression rem(15, 3)==0
would 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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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.
Now run the command
1
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
1
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) end
with &(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
1
Enum.each(min..max, &(play(&1)))
to
1
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.
1
2
3
4
5
6
#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
1
2
3
4
5
6
7
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…
Happy Coding…