FizzBuzz is a mental arithmetic game that got turned into a popular interview question. But what if we took the principle and created 8 different coding challenges from it that people may not have encountered before to really test someone's problem solving and development skills?
Well that is what I have done!
I think the below should be easy enough for beginners but also challenging with the extra stipulations for pros and having to combine solutions!
Final thing: I hope the below instructions are clear. However if any of the instructions are not clear please let me know in the comments so I can improve the questions!
Contents
- What is Fizz Buzz
- Instructions
-
1. FizzBuzz without using
%
- 2. FizzBuzz but it requires a button press!
- 3. FizzBuzz but it stores state!
- 4. FizzBuzz without loops
- 5. Stop logging to the console!
- 6. FizzBuzz where you can pass in the start and end numbers
- 7. Now do it in reverse!
- 8. FizzBuzz where you can pass in any words and numbers you want and Extra Credit!
- Submit your entries!
- Using this as an interview technique!
- Answers and final little bits
Skip to the instructions if you know what FizzBuzz is
What is FizzBuzz?
It is a simple game.
You start counting 1, 2 etc.
Every time you reach a multiple of 3 (3,6,9 etc) you replace the number with the word "Fizz".
Every time you reach a multiple of 5 (5, 10, 15 etc.) you replace the number with the word "Buzz".
Oh and if you reach a multiple of 3 AND 5 (15, 30, 45 etc.) you replace the word with "FizzBuzz".
Those are the rules.
In an interview question you are normally asked to output the numbers 1 to 100 and the relevant "fizz", "buzz" and "FizzBuzz" replacements.
A simple example of this that should make sense even if you are a beginner is
If you check the console it outputs the numbers and words as expected. You can use this as an example to work from / learn from if you like.
Instructions
You will be completing the same tasks whether you are a beginner or a pro.
However the pro version of this challenge has extra stipulations / requirements:
For beginners
Try and tackle each problem individually. You can develop different code for each solution if you want.
If you get stuck on a solution to one problem then just move onto the next one! They are not necessarily in difficulty order so you may find question 6 easier than question 5 for example.
At the end you should have 8 different solutions
For Pros
Each requirement continues onto the next question.
So by the end your one answer should work for all 8 requirements (if any conflicts in instructions occur you should always use the latest requirement - i.e. logging to console should be replaced with returning an array etc.)!
Oh and you also have a few extra requirements to deal with to make it even more interesting!
At the end you should have one "super solution" that covers all the points. Essentially you should have built a configurable FizzBuzz library
1. FizzBuzz without using %
Nearly every FizzBuzz answer you see uses the remainder (%
) operator.
For this challenge we have removed the remainder (%
) operator so you have to find an alternative way to check if a number should have Fizz, Buzz and or FizzBuzz logged to the console instead.
Beginners
Log each number / Fizz / Buzz / FizzBuzz to the console without using %
.
Pros
This one is a nice easy one to ease you in, just do the same as the beginners here! It gets tougher I promise!
2. FizzBuzz but it requires a button press!
In this challenge you have to attach your function to a button press somehow. This button should say "next".
Each time the button is pressed the next number / word should be logged to the console.
Beginners
Just add an "next" button and log the next number to the console each time it is pressed. It should start at 1 and increase each time the button is pressed (following FizzBuzz rules of course!).
It can keep going past 100 if you want or you can disable the button once 100 is reached for a bonus point!
Pros
You must include two extra buttons!
The first button should complete the rest of the numbers from the current state (so if your last number / word was "22" you should be able to press this button and it prints 23 - 100). This button should have the text "complete the run".
You should also include a reset button (with the text "reset") that returns the state to the beginning so the next button press logs "1" to the console etc.
3. FizzBuzz but it stores state!
Using your answer to the previous question you should now use Window.localStorage
to store the current number.
It must not store anything to localStorage
until the "next" button is pressed for the first time.
You should be able to reload the page, press the button and the next number should be logged to the console.
Beginners
You just have to be able to reload the page and the next value be returned on pressing the "next" button.
Pros
Don't forget that you need to be able to reset the state still and complete the run.
One stipulation here is that if you press the "reset" button you must remove your localStorage
entry entirely.
4. FizzBuzz without loops
In this exercise your FizzBuzz generator should use recursion.
No loops of any kind.
Beginners
You can just log the numbers / words for the numbers 1 to 100 to the console but your function must use recursion instead of loops.
Pros
As an extra stipulation when the 100 numbers / words have been logged to the console this should also log "done" after the 100th entry!
Oh and don't forget your other buttons still need to work!
5. Stop logging to the console!
Now your FizzBuzz generator should return the values it creates rather than logging to the console.
Beginners
Just return the next value and use a <div>
to display the number using a different function that calls your fizz buzz function. You can overwrite the number or keep a record and display each new number on a new line.
For clarity you should create a function "outputResult" or similar and this should call your "FizzBuzzGenerator" function, receive the value back from it and then output this to a <div>
on the page.
Pros
To make this more interesting it should return the current value (after pressing the "next" button), the previous value and the next value in that order.
It is up to you to account for errors caused by being at the start or the end of the list of numbers - you should return null
when this happens (e.g. the first output will be (null
, 1, 2) and the last will be (99, 100, null
...see next point though).
Don't forget that once you have reached 100 the next entry should state "done" and it should not increment any more (so effectively 101 is "done").
Also you should output each entry as a <table>
with the following format:
number | previous value | current value | next value |
---|---|---|---|
! 26 | Buzz | 26 | Fizz |
27 | 26 | Fizz | 28 |
28 | Fizz | 28 | 29 |
29 | 28 | 29 | FizzBuzz |
etc. etc.
As a final point here, "reset" should clear the table!
6. FizzBuzz where you can pass in the start and end numbers
A nice easy upgrade, your function should now accept any start number and any final number as integers.
To make your answer complete you should add two <input>
s to your example that take the minimum value and the maximum value.
Beginners
The numbers will always be positive integers and the start number will always be smaller than the end number.
The numbers can be between 1 and 10,000.
You need to add a button that calls your function next to or below your two inputs to be able to test this.
You can output to the console or put all the numbers in a <div>
.
Pros
If the start number is bigger than or the same as the end number then you must log this exact phrase "error, the start number must be smaller than the end number". It should be logged as an error.
You also need to account for negative integers so you can receive any numbers between - 10,000 and 10,000.
Zero should output "0" not FizzBuzz!
If any other errors occur (such as non numerical or null values being passed) you should log a generic error "input values are incorrect".
7. Now do it in reverse!
Yes this is a mean one!
Now your function should also accept a 3rd parameter. This time if that parameter is set to true
the numbers should start at the maximum and count backwards to the minimum, if set to false
they should return in ascending order the same as before.
Beginners
You can just use the numbers 1 to 100 and work out how to reverse the numbers if this parameter is passed.
So you could have - myFizzBuzzFunction(false)
(which will still write 1 - 100). However myFizzBuzzFunction(true)
will return 100 - 1 (reversed).
Pros
Bear in mind that "done" now needs to appear after the lowest number if the order is reversed.
You also need to make the third optional parameter so that we can call your function with myFizzBuzzGenerator(smallNo, largeNo)
or with myFizzBuzzGenerator(smallNo, largeNo, false)
, myFizzBuzzGenerator(smallNo, largeNo, true)
etc. myFizzBuzzGenerator(smallNo, largeNo, true)
should be the one that reverse the order.
You also have the fun task of working out how to account for all of the previous stipulations (what if the number is currently 26 and we change the order) etc.
Finally you should add a checkbox next to your inputs you added previously that when checked reverses the order!
So you should now have 3 buttons, "next", "complete the run" and "reset" plus a checkbox with the label "Reverse order". If "Reverse Order" is checked then pressing "Next" will decrease the number by one and pressing "complete the run" will count downwards from the current number.
One last thing: you will have to add an extra column to your results table based on whether the checkbox is checked or not.
number | direction | previous value | current value | next value |
---|---|---|---|---|
! 26 | forward (or false) | Buzz | 26 | Fizz |
27 | forward (or false) | 26 | Fizz | 28 |
28 | forward (or false) | Fizz | 28 | 29 |
29 | forward (or false) | 28 | 29 | FizzBuzz |
28 | backwards (or true) | Fizz | 28 | 29 |
27 | backwards (or true) | 26 | Fizz | 28 |
8. FizzBuzz where you can pass in any words and numbers you want.
This time the function must accept an unlimited number of divisor / word pairs.
So for example:-
let wordsAndDivisors =
[
{"word": "Fizz", "divisor": 3},
{"word": "Buzz", "divisor": 5},
{"word": "Fluff", "divisor": 7}
]
////your function should log
1
2
"Fizz"
4
"Buzz"
"Fizz"
"Fluff"
8
"Fizz"
"Buzz"
11
"Fizz"
13
"Fluff"
"FizzBuzz"
[...]
92
"Fizz"
94
"Buzz"
"Fizz"
97
"Fluff"
"Fizz"
"Buzz"
Beginners
You will receive between 2 and 10 different word & divisor pairs.
A couple of examples to test against are:
const wordsAndDivisors =
[
{"word": "Fizz", "divisor": 3},
{"word": "Buzz", "divisor": 5},
{"word": "Fluff", "divisor": 11}
]
myFunction(wordsAndDivisors);
// 3 = Fizz, 5 = Buzz, 11 = Fluff, 33 = FizzFluff, 55 = BuzzFluff.
const wordsAndDivisorsTwo =
[
{"word": "Fizz", "divisor": 3},
{"word": "Buzz", "divisor": 5},
{"word": "Fluff", "divisor": 7},
{"word": "Biff", "divisor": 11},
{"word": "Buffer", "divisor": 17},
{"word": "Tink", "divisor": 23}
]
myFunction(wordsAndDivisorsTwo);
// 17 = Buffer, 46 = Tink, 77 = FluffBiff, 85 = BuzzBuffer.
Pros
You have to account for 0 - n entries in the format described.
This is also an optional parameter. If no entries are passed just return the relevant numbers between min and max in the relevant direction.
Your function should now be myGeneratorFunction(min, max, directionOptional, wordsAndDivisorsOptional)
For clarity if you stop here then:-
-
myGeneratorFunction(1,100)
would just return the numbers 1 to 100 -
myGeneratorFunction(1,100, true)
would return the numbers 100 to 1 -
myGeneratorFunction(1,100, false, wordsAndDivisors)
would return 1 to 100 with fizz, buzz and fluff replacements!
Now go tidy your code up and submit it in the comments!
Or if you want one last minor challenge to make it even more useful:
Go for Extra credit
Create a way of accepting the parameters as an object (settings / config) to allow for different scenarios.
You can dictate the settings object structure to make this easier.
If you decide to pass an object in then you can also have bonus points for making min and max numbers have defaults / optional parameters of:
- 1 for min
- 100 for max
- default direction should be forward
- default word:divisor pair should now be normal FizzBuzz instead of nothing!
For clarity we should be able to call your function as myFizzBuzzGenerator()
and it do normal FizzBuzz in a forward direction for the numbers 1 to 100. (Note that this is different behaviour to the non extra credit version).
But we could also call it with myFizzBuzzGenerator(myGeneratorSettings)
and the min number, the max number, direction etc. all override the defaults if they are passed in!
Oh and everything previous still counts!
Extra Extra credit!
Come up with other "requirements" this library might have.
See if you can make it fully extensible so people can create plugins. Could you supply it with the Fibonacci sequence or any sequence of numbers. Could you make it output words for numbers? Could you turn it into a web component or a React module?
Add any requirements you can think of and then your solutions to those problems!
The end - what should you be looking for?
So depending on whether you went for the beginner or the pro version you should either have 8 different FizzBuzz variations or one mega variation.
For beginners
You just have to ensure that each one functions as expected and outputs the information as requested.
One thing I would suggest is that you comment any particularly confusing parts for the next person who has to work on your code.
If you have managed to create all 8 versions why not move up to the semi-pro tier and see if you can combine two, three or even four examples together, but using the beginner instructions!
Pros
High standards here.
You should ensure your code is:-
- Easy to understand and uses logical variable names etc.
- Is efficient, nested loops are a no no (but if you have nested loops for this I am not sure what you are doing anyway! 😋🤣).
- Bonus points if you have made it easily extensible and split parts off into different functions where applicable.
And to recap to see if you complete the challenge at this point you should have:
- a function that does not use the remainder (
%
) operator! - a function that accepts a small number, a large number, a flag to reverse and the word divisor pairs.
- two inputs and a checkbox for small, large and whether to reverse.
- three buttons "next" to add (or remove) 1, "complete the run" which continues to the max or min number and then outputs "done" and a "reset" button which returns to the max or minimum number depending on direction.
- reset button should clear all local storage!
- Error checking for every passed variable etc.
- Recursion rather than a loop.
- "0" should output "0" not FizzBuzz or any other word combination!
- Should work with an unlimited (or zero) "word:divisor" pairs.
- Oh and I shouldn't have to say it but you inputs should be properly labelled
- You should have a settings object that you can pass in with defaults for extra credit!
Submit your entries!
All answers submitted should be in JavaScript, however you can obviously complete these challenges in any language you want!
There are no prizes but an opportunity for others to critique your work and offer tips and or learn from your code.
Leave a comment with your example(s)
jsFiddle
You can include a jsFiddle in your comment with liquid tags in the following format:-
{% jsfiddle <url of fiddle> result js html %}
CodePen
You can include a CodePen in your comment with the following liquid tag:
{% codepen <url of pen> default-tab=result, js, html %}
Any other way you want!
If you don't want to use jsfiddle or CodePen then any other code sandbox will do! Just provide a link to it or see if there is a liquid tag for your chosen sandbox
Using this as an interview technique!
For beginners / new developers they should be able to complete most of the tasks individually. It also lets you see how they approach problems.
Obviously using the "pro" tasks as a coding interview it is missing soft skills, API interactions, design / CSS skills etc. but overall I think there is enough there to get a good feel for whether a developer is up to scratch on basic principles, code structuring, following a brief, whether they read all instructions first to see potential pitfalls in their solution or tackle each problem at a time and refactor it later etc.
There are even chances to assess their ability to spot potential oversights in the brief (for example: if I reach "done" and then change direction should I be able to run the application without resetting, do you want "done" to be output as an extra row in the table or should the last row be "100" - if so what should the last column contain for "next number" etc. etc.).
As you can see it has a lot of benefits over a typical question and answer coding assessment.
It isn't designed as a "take it and use it as is" example, but more of an idea how you can build upon previous questions to assess different real world problem solving skills that singular questions tend to miss.
I also like this as a principle as it doesn't rely on particular knowledge. I don't need to know a particular algorithm to solve a particular problem that I will never use anywhere other than in an interview, it lets me use skills I should have in my head.
Anyway it is just my opinion, some of you may disagree but I am seriously considering refining this technique as the basis of interviews when I am hiring.
Answers next week!
Make sure you follow me as I will release my solution and or the best solution for the beginner versions as well as my "kitchen sink" solution for the pro version!
Special instructions for @afif
You can try and complete the beginner challenges without JavaScript...just because I know how much JS hurts you! Oh and it can just work in one browser too!
You can use css vars as inputs etc. Output the information however you want! It doesn't have to be accessible either 😋🤣
(and for anyone confused by this, Temani and I have a running joke where he is hurt by anything not using CSS as he is a CSS ninja!)
Anyone else who fancies the challenge can do this also as I can imagine there are some really interesting solutions that are beyond my meagre brain!!
Top comments (15)
Done!
It's still undergoing refactoring and extra credit exercises, but I'm kinda busy (I got exams!). It might be done in 24 hours.
When you have tidied up (and fixed a naming bug, hint hint
wordmap
andwordMap
) then let me know!After an initial look though it looks good ❤, but I won't test properly until you tell me to!
P.s. my instructions might not have been clear enough but there should be no "decrease" button, the "next" button coupled with the checkbox should dictate direction. I will check that the instructions don't cause confusion there.
You can consider it done! After a lot of testing and stuff, it seems bug free. Test it out and tell me if there's any problems.
About my attempt
Challenge 1: Was not very hard, just had to reimplement division, which was pretty easy
Challenge 2: Still pretty easy. Just had to add some event listeners. This was made even more easy by the fact that my
fizzbuzz
function only checked a single number.Challenge 3: Just had to add a few lines
Challenge 4: This was easy at first, but would ultimately be the biggest problem and I had to rewrite it.
Challenge 5: That was literally what I was doing. I was just logging to the console outside my
fizzbuzz
function. Just needed to change a few lines.Challenge 6: Easy again, because my
fizzbuzz
function just checked one number, and I just had to change the numbers in the recursion I was doing earlierChallenge 7: Easy, but this was where I made 99% of my silly mistakes (I was trying to reverse recursion, until I realized I need to pass in the minimum). This part took the most time.
Challenge 8: This was pretty easy, because I'm used to manipulating objects in this manner.
What I learned:
PS: These challenges are awesome, would love it if you make more! I might even make a challenge myself! (I did once but no one answered. I guess it was too hard)
Hmm the decrease button came up a accidentally because of my initial confusion, and I decided to keep it. Consider it a bonus.
I have added the following paragraph to section 7 to clarify this part as it was not well written:
"So you should now have 3 buttons, "next", "complete the run" and "reset" plus a checkbox with the label "Reverse order". If "Reverse Order" is checked then pressing "Next" will decrease the number by one and pressing "complete the run" will count downwards from the current number. "
My CSS only solution. Work from 1 to infinity (chrome and edge only)
codepen.io/t_afif/pen/dyWpree
Will probably optimize later to cover more cases.
I knew I could count on you to use CSS to solve JS problems!
Looking at it it is more difficult than I thought to do with CSS.
I thought a
:before
and:after
combo was going to be the trick but didn't actually think about how to fix positioning like that!Really interesting solution! ❤
I hope the instruction are clear and this is a fun Sunday challenge for people.
My answer will come out next week / the best answers for both beginner and pro.
Oh and if you are one of those people who really like to show off - you can code golf your answer if you want (but still in JavaScript please)!
I look forward to seeing what people submit (if anyone does that is!)!
oh and please ensure it is a runnable sandbox fiddle / pen etc. so people can play with your entry!
Mistake – You mention a direction in the table in step 5, but there's no decrease button!
Ah now I get you, I changed the order of challenges and forgot about that part. I think I have now accounted for that, great spot!
Thanks for pointing it out! ❤
Wow, great challenge! This inspired me to make a small extra challenge:
Classic fizzbuzz, but:
"use strict"
eval
or such (obviously)let
/var
%
) and noMath
Objectif
/else
const
==
,===
,!=
,!==
)return
statements{}
😈It's solvable, have fun :D
That sounds horrific! If I get chance I will see if I can put a solution together but as the England vs Italy match is on at the moment it will have to wait! 😋
Check out FizzBuzz-Everything, a community driven GitHub repo with FizzBuzz written in a whole lotta languages!
Thats really cool, I will include it in the part 2 / follow up piece if I remember. Thanks for sharing!
Looks good, I will have a run through it soon!