I was asked to solve a classic programming question today, the “FizzBuzz” problem.
The problem statement:
- Write an algorithm that prints the numbers from 1 to 100.
- for multiples of three print “Fizz” instead of the number
- for multiples of five print “Buzz” instead of the number
- For numbers which are multiples of both three and five print “FizzBuzz”
To spice it up with some more UI work here’s some additional criteria
- Create a basic web page
- have inputs for two 2 multiples used in the algorithm (e.g. 3 and 5 in the base case)
- an input used to determine how many numbers to go through
- a button that triggers the custom fizz buzz calculation to be ran and updates the page with the results
Feel free to use any javascript library you’re familiar with to accomplish this task.
So this is how I tackled it:
First, I’m familiar with jQuery more than anything else at the moment, so this example will leverage it. Because this was essentially just a JavaScript/jQuery coding test I just grabbed HTML5 Boilerplate as a baseline. It included the libraries, base html, and css that I needed.
This is the stripped down HTML that we are going to be working with. First I am going to markup the form that we will be using, I’m using the fancy new HTML5 number input and defining some minimum and base values. Next I chose to use an unordered list for this example.
<form id="fizzbuzzform">
<fieldset>
<label for="num1">Enter Fizz Number:</label>
<input type="number" id="num1" min="0" value="3"></input>
<label for="num2">Enter Buzz Number:</label>
<input type="number" id="num2" min="0" value="5"></input>
</fieldset>
<fieldset>
<label for="totalitems">Enter Number of items to iterate through:</label>
<input type="number" id="totalitems" min="0" value="100"></input>
</fieldset>
<input type="submit" id="submit" value="Submit"></input>
</form>
<ul id="fizzbuzzlist">
</ul>
Next we are going to need a function to call
function fizzBuzz(){};
We are going to need to pass some parameters to it for the 3 inputs
function fizzBuzz(fizz, buzz, iterations){};
Next we need to loop over the amount of iterations
function fizzBuzz(fizz, buzz, iterations){
for (var i=1; i<=iterations; i++){
//this will go through how ever many iterations are set.
}
};
We now need to start looking at the logic of determining if the number is the fizz or buzz number. The core logic of this is based on the Modulus operator or in JavaScript the % operator. What the % operator does is provide the remainder of a division operation. For 15 % 5, there is no remainder left because it is divisible by 5. For 7 % 3 there is a remainder of 1. To determine if the iteration is a number that is divisible, we need to see if the result is 0. That means that it will be a Fizz or Buzz number.
function fizzBuzz(fizz, buzz, iterations){
for (var i=1; i<=iterations; i++){
if (i % fizz == 0){
//this is fizz number
}
}
};
Throw in a || to test for the buzz number.
function fizzBuzz(fizz, buzz, iterations){
for (var i=1; i<=iterations; i++){
if (i % fizz == 0 || i % buzz == 0){
//this is a fizz or buzz number
}
}
};
One of the other things that we need to do is to make sure that we aren’t dividing by 0. I believe in JavaScript that it would return an undefined result. But in Math I believe it’s called a NaN, or Not a Number.
function fizzBuzz(fizz, buzz, iterations){
for (var i=1; i<=iterations; i++){
if (i != 0 && (i % num1 == 0 || i % num2 == 0)){
//this is a number above 0 that is a fizz or buzz number
}
}
};
So at this point, we know if the number in question is a fizz or buzz number, but we don’t know which one of the two.
function fizzBuzz(fizz, buzz, iterations){
for (var i=1; i<=iterations; i++){
if (i != 0 && (i % num1 == 0 || i % num2 == 0)){
if (i % fizz == 0) {
//output fizz
};
if (i % buzz == 0) {
//output buzz
}
}
}
};
Because of how the problem is phrased we need to output the iteration number if it isn’t a fizz or buzz number. So we need to add an else to the first if statement.
function fizzBuzz(fizz, buzz, iterations){
for (var i=1; i<=iterations; i++){
if (i != 0 && (i % num1 == 0 || i % num2 == 0)){
if (i % fizz == 0) {
//output fizz
};
if (i % buzz == 0) {
//output buzz
}
} else {
//output the iteration number
}
}
};
Now comes the time we add some string building. In this particular example I’m going to use an unordered list for the HTML. We could have used just about anything here, this is just what I picked.
We need to initialize an empty string before the for loop. The reason we do that is for scope reasons and we wouldn’t want to keep reinitializing the same variable.
function fizzBuzz(fizz, buzz, iterations){
var fizzBuzzListItems = "";
for (var i=1; i<=iterations; i++){
if (i != 0 && (i % fizz == 0 || i % buzz == 0)){
//building out a string and appending it to the list
fizzBuzzListItems += "<li>";
if (i % fizz== 0) {
fizzBuzzListItems += "Fizz";
};
if (i % buzz == 0) {
fizzBuzzListItems += "Buzz";
}
fizzBuzzListItems += "</li>"
} else {
//if the modulus is 0 write out the iteration number
fizzBuzzListItems += "<li>" + i + "</li>";
}
}
};
The last thing that we need to do for the function is to return the HTML that we just built up.
function fizzBuzz (fizz, buzz, iterations){
var muListItems = "";
for (var i=1; i<=iterations; i++){
if (i != 0 && (i % fizz == 0 || i % buzz == 0)){
muListItems += "<li>";
if (i % fizz == 0) {
muListItems += "Fizz";
};
if (i % buzz == 0) {
muListItems += "Buzz";
}
muListItems += "</li>"
} else {
muListItems += "<li>" + i + "</li>";
}
}
return muListItems;
}
Now we need to setup a listener event for when the user submits the form. There is a gotcha in this though. When the user submits a form, the default action is to post the form and render a new page. If you don’t prevent that behavior then you will probably see your results flash for a second and then get reset because the page reloaded. So we are going to add a .preventDefault() so that the post isn’t performed. We also want this event listener to be added on $(document).ready(). Also notice that we did not put a listener on the Submit button, but on submit action of the form.
$(document).ready(function(){
//setting a listener for the Submit action.
$('form').submit(function(event){
//preventing the default submit action as it would clear the results.
event.preventDefault();
//pass the function as a parameter to the $.html() with the appropriate values as inputs
//write out the HTML to the selected markup element.
//this is done once so that multiple writes to the DOM are not made in the iteration
$('#fizzbuzzlist').html(
fizzBuzz ($('#num1').val(), $('#num2').val(), $('#totalitems').val())
);
});
});
So at this point we are done. When you load the page there are 3 inputs for the Fizz Number, Buzz Number, and the amount of numbers to check. When you hit submit, it returns the results as list items and inserts them into the unordered list.