Recursive FizzBuzz in JavaScript
oksanadev
Posted on November 9, 2020
The Fizz Buzz test is a simple example of a tech interview question designed to test job candidates. It reads as follows:
Write a function that prints the numbers from 1 to 100. For multiples of three print “Fizz” instead of the number and for multiples of five print “Buzz” instead of the number. For numbers which are multiples of both three and five print “FizzBuzz”.
It is a basic exercise to practice conditionals and modulo/remainder operator. If you can think of one obvious solution, you might be surprised to see that there are lots of ways this can be solved in JavaScript. For example, this article suggests 20 JavaScript ways to solve FizzBuzz!
The classic JavaScript solution though would look like this (using an old-fashioned for loop):
for (let i = 1; i <= 100; i++) {
if (i % 3 === 0 && i % 5 === 0) console.log('FizzBuzz');
else if (i % 5 === 0) console.log('Buzz');
else if (i % 3 === 0) console.log('Fizz');
else console.log(i);
}
If you love one-liners, there is also a short version of it:
for (let i = 1; i <= 100; i++) console.log(i % 3 ? i % 5 ? i : 'Buzz' : i % 5 ? 'Fizz' : 'FizzBuzz')
However, as our code is supposed to be read by humans (the machine will read it in any form), developers are generally advised against making the life of fellow programmers even more complicated than it already is.
While moving forward in my coding journey, I have attempted to implement a recursive version of FizzBuzz.
Recursion is the act of a function calling itself. Thus, recursion occurs any time a function calls itself inside itself, potentially creating an infinite loop Source.
A recursive function has 2 main ingredients: a base or exit condition and at least one recursive case. No exit condition would lead to an infinite loop.
A basic solution for a recursive FizzBuzz would be to create an inner recursive function that uses the initial value of the counter variable declared in the scope of the parent function. It represents a closure in a broader context:
You have a closure when a function accesses variables defined outside of it.
In our case, the basic condition states: “if the parameter passed to the inner function (counter) is greater than the parameter passed to the main function - 100, exit the function”.
const fizzBuzz = (randomNum) => {
let counter = 1;
const func = (counter) => {
if (counter > randomNum) return;
if (counter % 5 === 0 && counter % 3 === 0) console.log('FizzBuzz');
else if (counter % 5 === 0) console.log('Buzz');
else if (counter % 3 === 0) console.log('Fizz');
else console.log(counter);
func(counter + 1);
};
func(counter);
}
fizzBuzz(100)
However, this can be simplified by using default values of parameters (ES6 feature). So, the cleaner version would look like this:
const fizzBuzz = (randomNum, counter = 1) => {
if (counter > randomNum) return;
if (counter % 5 === 0 && counter % 3 === 0) console.log('FizzBuzz');
else if (counter % 5 === 0) console.log('Buzz');
else if (counter % 3 === 0) console.log('Fizz');
else console.log(counter);
fizzBuzz(randomNum, counter + 1);
};
fizzBuzz(100)
The counter parameter is assigned a default value of 1. Thus, we don’t need the inner function anymore as its only role was to grab the initial counter value from the outer scope.
As a bonus, here is a recursive FizzBuzz running downwards:
const fizzBuzz = (randomNum) => {
if (randomNum === 0) return;
if (randomNum % 5 === 0 && randomNum % 3 === 0) console.log('FizzBuzz');
else if (randomNum % 5 === 0) console.log('Buzz');
else if (randomNum % 3 === 0) console.log('Fizz');
else console.log(randomNum);
fizzBuzz(randomNum - 1);
}
fizzBuzz(100)
Recursion might be difficult to grasp at first. These simple examples of the classic programming puzzle were designed with an aim to make this topic a little bit clearer.
Cover photo by Céline Haeberly on Unsplash
Posted on November 9, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.