FizzBuzzBazz: How to answer and how NOT to answer

Don’t let a little twist to FizzBuzz lead you down a rabbit hole

FizzBuzz is the infamous weedout coding challenge that some hiring managers use as a warm-up or a confidence boosting test before the real test begins. If you are reading this, you probably know how the question and the answer goes, but I will put it down here for reference again.

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”.

The textbook answer to this question to this prompt is as follows:

const fizzbuzz = () => {

for (let i = 1; i <= 100; 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);

}

}

} fizzbuzz() // 1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7 .. 14, 'FizzBuzz', 16, 17 ..

The general consensus I got on how to answer FizzBuzz is to not get cute, and just follow the exact logic like above and move on.

Let the potential employer know that you are aware of if-else statements, iteration, and outputting Hello, World to the console and move on to the real interview.

However, an interviewer may add a little wrinkle to the problem and may ask you something like:

Okay, now I would like fizzbuzz() to handle multiples of 7. So if a number is a multiple of 7, I want to output ‘Bazz.’ For a multiple of 7 AND 3, I want to output ‘FizzBazz.’ For a multiple of 7 AND 5, I want to output ‘BuzzBazz.’ For a multiple of 3, 5, AND 7, I want to output ‘FizzBuzzBazz’.

So the rabbit hole to avoid here is to continue adding onto if-else statements like the following:

const fizzbuzz = () => {

for (let i = 1; i <= 100; i++) {

if (i % 3 === 0 && i % 5 === 0 && i % 7 === 0) {

console.log('FizzBuzzBazz');

} else if (i % 3 === 0 && i % 5 === 0) {

console.log('FizzBuzz');

} else if (i % 3 === 0 && i % 7 === 0) {

console.log('FizzBazz');

} else if (i % 5 === 0 && i % 7 === 0) {

console.log('BuzzBazz');

} else if (i % 3 === 0) {

console.log('Fizz');

} else if (i % 5 === 0) {

console.log('Buzz');

} else if (i % 7 === 0) {

console.log('Bazz')

} else {

console.log(i);

}

}

} fizzbuzz() // 1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 'Bazz'...13, 'Bazz', 'FizzBuzz', 16, 17..

We can see that just one little wrinkle to our fizzbuzz() function bloats up our if-statements exponentially. If you do actually end up writing the above on the whiteboard, the interviewer will most likely follow up by asking you to associate 9 with ‘Bozz.’

Then, unless you had the foresight to triple space your lines on the whiteboard when starting out the problem, you most likely won’t have any real-estate to work with.

The Solution: String Concatenation

By leveraging string concatenation, we can get out of the else if entanglement as follows:

const fizzbuzz = () => {

for (let i = 1; i <= 100; i++) {

let output = '';

if (i % 3 === 0) { output += 'Fizz' };

if (i % 5 === 0) { output += 'Buzz' };

if (i % 7 === 0) { output += 'Bazz' };

if (output === '') { output = i };

console.log(output);

}

}

For every integer from 1 to 100 we iterate through, we reset output to an empty string, then concatenate any string value that the integer in the given loop is associated with, then log the resulting output to the console and move onto the next integer.

If an integer is not associated with any specified multiple (say i = 8 ), the output will get converted into the integer the loop is currently iterating through.

Now if the interviewer wanted you to handle a case where 9 is associated with ‘Bozz,’ we just slip in an additional line of if (i % 9 === 0) { output += 'Bozz'} and we save ourselves from some permutation-logic headaches.

The Optimized(?) Solution: Throw in a Hash

Perhaps at this point, the interviewer may complain about how the code is too repetitive and may ask you to clean up the code.

In that case, the interviewer may just be subtly testing your knowledge of Hashes and we can refactor our code as follows:

const fizzbuzz = () => {

const fizzHash = {3: 'Fizz', 5: 'Buzz', 7: 'Bazz'}; for (let i = 1; i <= 100; i++) {

let output = '';

for (let num in fizzHash) {

if (i % num === 0) { output += fizzHash[num] }

}

if (output === '') { output = i };

console.log(output);

}

}

The pro of this version is that if we wanted to add in additional cases, i.e. 9: ‘Bezz’, 13: ‘Lizz’ 21: ‘Luzz’, we just tack on additional key-value pairs in our fizzHash constant.

This rendition is definitely less repetitive than the previous solution, as we do not see a block of near-identical if-statements.

Having said that, the code before our “optimization” certains reads nicer and is easier to follow along — especially when only dealing with ‘Fizz,’ ‘Buzz,’ and ‘Bazz.’

If were ever asked to answer the classic FizzBuzz question and we started out by writing out a solution involving iterating through a hash, we are definitely finding ourselves in the ‘cute’ or ‘over-engineering’ territory.

Closing Thoughts

As this great post by a senior developer suggests, write readable and dumb code first. If the following questions that the interviewer is asking are leading you into writing a block of messy code, don’t panic, step back, let the interviewer know that the current approach isn’t very efficient, and try to come up with a better solution.

In the case of FizzBuzzBazz, getting unstuck didn’t involve going straight for the top shelf and picking out a fancy new data structure. (i.e. array of subarrays, Maps, Sets, Hashes, etc.) It was just a little tweak in the if-statement logic and using string concatenation to our advantage. Using Hashes was just a nice extra touch depending on whom you ask.

I hope you enjoyed this post. Feel free to leave a few claps down below!