How to Tackle FizzBuzz - The Famous Coding Challenge
Trivial Pursuit
It's a simple, even trivial coding interview question, but even senior coders sometimes fail it and not only becuase the interview is stressfull.
I also think it's a great opportunity to learn how to turn a very specific question from a trivial solution into a more elaborate approach.
Note: all code examples in this article will be in pure JS
First, let's review the challenge itself:
Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.
Without further ado let's try to tackle it using a super naive (and wrong) implementation:
for (let i = 1; i <= 100; i++) {
console.log(i)
if (i % 3 === 0) console.log('Fizz')
if (i % 5 === 0) console.log('Buzz')
if (i % 3 === 0 && i % 5 === 0) console.log('FizzBuzz')
}
Why is this wrong? First of all it prints the value even in cases of Fizz/Buzz/FizzBuzz. But also it will output both "Fizz", "Buzz" and "FizzBuzz" for a full match, which clearly isn't what was requested.
So let's add else to prevent multiple console logs this way:
for (let i = 1; i <= 100; i++) {
if (i % 3 === 0) console.log('Fizz')
else if (i % 5 === 0) console.log('Buzz')
else if (i % 3 === 0 && i % 5 === 0) console.log('FizzBuzz')
else console.log(i)
}
Clearly there's something wrong again. "FizzBuzz" is never called! Why is that? Well, it's because the first condition covers also for the last one and because of the "else" the last one will never be called.
How do we fix this? Simple. Place the last condition first! If something is "FizzBuzz" then log it, if not, then check for either 3 or 5.
for (let i = 1; i <= 100; i++) {
if (i % 3 === 0 && i % 5 === 0) console.log(i, 'FizzBuzz')
else if (i % 3 === 0) console.log(i, 'Fizz')
else if (i % 5 === 0) console.log(i, 'Buzz')
else console.log(i)
}
The Broader Context
But what happens if we wish to solve this for other numbers than 100? Instead of using a hard-coded value, let's create a function which handles a broader case.
function fizzBuzz(to) {
for (let i = 1; i <= to; i++) {
if (i % 3 === 0 && i % 5 === 0) console.log('FizzBuzz')
else if (i % 3 === 0) console.log('Fizz')
else if (i % 5 === 0) console.log('Buzz')
else console.log(i)
}
}
Challenge yourself: how about adding a parameter to start from any number? How about replacing the Fizz and Buzz triggers to a dynamic pair of numbers?
Moving Away from Logs
A function which logs something isn't very useful. Let's pretend that its output could be useful somehow, so let's make it return an array instead of logging individual lines.
function fizzBuzz(to) {
const result = []
for (let i = 1; i <= to; i++) {
if (i % 3 === 0 && i % 5 === 0) result.push('FizzBuzz')
else if (i % 3 === 0) result.push('Fizz')
else if (i % 5 === 0) result.push('Buzz')
else result.push(i)
}
return result
}
What Next?
There's a lot that could be done with said challenge. We could use a functional programmning approach. We could do away with the for loop completely. We could make it a fully flexible function to tackle more than just two numbers and messages.
Try to tackle it yourself. And if you need help boosting your programming knowledge, you could always cosult with a mentor.
Happy coding!