Published
- 6 min read
A Comprehensive Guide to the FizzBuzz-Problem
Lets explore the classic FizzBuzz-Problem. What is the problem? What is a potential solution? Should you use it in an interview context?
The Problem
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”.
This is a Math problem. At the core this is a problem of finding the numbers that are divisible by 3 and 5.
You will demonstrate that you are knowledgeable about following topics:
- The Modulo Operator
- Loops
- How to output to the console in your chosen language
- How to write a function and how to use variables
The FizzBuzz Solution
Now there are many different ways to solve this problem. I will present you a couple of solutions:
The Common Solution
const fizzBuzz = (): string[] => {
const result: string[] = []
for (let i = 1; i <= 100; 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.toString())
}
}
return result
}
What is good about this solution?
- It solves the problem.
What is bad about this solution?
- It has a magic number
100
- It duplicates the modulo operators
- It is difficult to test
The Optimized Solution
const fizzBuzz = (n: number = 100): string[] => {
const result = []
for (let i = 1; i <= n; i++) {
const divBy3 = i % 3 === 0
const divBy5 = i % 5 === 0
const str = `${divBy3 ? 'Fizz' : ''}${divBy5 ? 'Buzz' : ''}`
result.push(str || i.toString())
}
return result
}
What is good about this solution?
- It is very efficient.
- It stores the values from the modulo operations in variables.
What is bad about this solution?
- It is difficult to test
- It is hard to extend with more numbers.
- Abbreviations for variable names.
The Solution I Would Like to See
This solution represents my personal values. The code needs to work. Additionally I would like to see the solution as readable as possible. I do not care about the performance or if the solution is the optimal one.
Unlike most people I am using two different functions to solve the problem. I am optimizing for testing. By writing two functions it is easier to test the logic. In fact in an interview situation I would follow up and ask the candidate to write test cases for the logic.
const fizzBuzz = (n: number = 100): string[] => {
const output: string[] = []
for (let i = 1; i <= n; i++) {
output.push(convertToFizzBuzz(i))
}
return output
}
const convertToFizzBuzz = (n: number): string => {
const divisibleBy3 = n % 3 === 0
const divisibleBy5 = n % 5 === 0
if (divisibleBy3 && divisibleBy5) {
return 'FizzBuzz'
} else if (divisibleBy3) {
return 'Fizz'
} else if (divisibleBy5) {
return 'Buzz'
} else {
return n.toString()
}
}
What is good about this solution?
- It is readable.
- It is testable.
What is bad about this solution?
- It is not efficient.
The FizzBuzz Problem in the Context of a Job Interview
It is quite common that during a job interview, instead of going into a full technical interview, you are asked to solve the FizzBuzz problem on a piece of paper. It is used as a smoke test to see if the candidate has basic coding skills.
The Fundamental Problem with FizzBuzz
It is quite unlikely that you need a developer that can solve Math Problems. While many developers have good math skills it is usually not the type of problems you will have to solve on a day to day basis.
When you are interviewing a recent graduate - what is the point of the question. He probably will not have gotten his degree if he cannot code. In the worst case you will have to train him on the job. But that is the risk of hiring a student.
On the other hand if you are asking this question to an experienced developer - it really does not prove anything. You may expose that he did not work on math problems recently. It does not expose his thought process or his capability to solve problems. You stripped the developer from common tools.
What does it mean when the candidate cannot solve the problem?
The one thing I have noticed in interviews when this question was asked. In most cases the candidate was not familiar with the modulo operator.
You then could argue the candidate should be able to solve the problem without the modulo operator. The candidate could use something like Math.floor(n / 3) === n/3
or Math.floor(n / 5) === n/5
to find the numbers that are divisible by 3 and 5.
This line of thought is flawed. The candidate does not have a lot of experience solving Math problems. Thus it does not matter if he knows modulo or can work around it.
What can you learn from the candidates solution?
The most important thing is to concider that the solution will be written as throw away code. It does not have to fulfill the requirements of the code you write for your project. Thus it actually does not matter which solution the candidate presents.
Further on you anyway cannot learn a lot from the code the candidate writes. The problem is now so common in interview preparation materials, that it is not worth asking the candidate to solve the problem. There is a high chance the candidate memorized it.
If the candidate is not familiar with the problem - he wrote the code under pressure and stress - which probably did not create his best work.
Conclusion
If you want to ask the question in the context of an interview, really ask yourself “What exactly do you think that you will learn from this question?” - The time in an interview is limited, don’t waste it.
It is a good small interesting exercise to think about. Especially to write variants of FizzBuzz just to see if you can find a different solution. (There is always going to be a tradeoff)
FizzBuzz is a classic interview question. But it is a question that probably should be left to the history books.