One of the most common exercises in old-school interviews is the classic “FizzBuzz.” The instructions for this exercise are pretty simple:
We get a list of numbers from 1 to N. When a number is divisible by 3
, we change the value to "Fizz"
. When a number is divisible by 5
, we change the value to "Buzz"
. If we can divide the number by both 3
and 5
, we show "FizzBuzz"
. If none of the above applies, we just keep the number. Nowadays, any company with some respect for their candidates would avoid exercises like this, but it is still fun to do some code golf with it to see what’s the shortest version we can make. I came up with this one (64 characters long):
[ ... Array ( 100 )]. map ( ( _ , i ) => ( ++ i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i )
Sure thing, here’s the same code with comments:
// We use spread over a newly created array of 100 elements
// without the spread `map` doesn't work because the array is empty...
// Then we map over it...
// We ignore the first element `_` which is undefined, and use the index `i`
// First we do ++i because we start in `1` not `0`.
// We use a ternary so if ++i is divisible by 3 "Fizz", if not empty string.
( ++ i % 3 ? "" : " Fizz " ) +
// Same as above, but this time with 5 and "Buzz".
// At this point we have either "Fizz", "Buzz",
// both concatenated "FizzBuzz", or an empty string, which is falsy.
// So if we have that falsy value, we go to the index value.
If we don’t care about starting with the value 1
, then we can remove the ++
, making it even smaller:
[ ... Array ( 100 )]. map ( ( _ , i ) => ( i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i )
I also tried other variants but it is always bigger. This one uses spread with Array.prototype.keys
, so we don’t need to use the index, and we can use the value of the items:
[ ... Array ( 100 ). keys ()]. map ( i => ( ++ i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i )
Maybe using Array.from
? Nope, this is also bigger:
Array . from ( Array ( 100 ), ( _ , i ) => ( ++ i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i )
I also tried using that useless _
attribute like this:
[ ... Array ( 100 )]. map ( ( z = " zz " , i ) => ( ++ i % 3 ? "" : " Fi " + z ) + ( i % 5 ? "" : " Bu " + z ) || i )
Or even using nasty declarative stuff like this:
i = 0 , o = []; while ( i ++< 100 ) o . push (( i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i )
But it always ends up being larger. So I opened the challenge to the community:
So yeah, this is the challenge. I was wondering if there are smaller versions of this algorithm that we can achieve in JS. If someone reading this article has any ideas, send me a message, and we can add them below.
@SiddharthShyniben made this version:
a = []; for ( i = 0 ; ++ i < 101 ; a . push ( i % 5 ? f || i : f + " Buzz " )) f = i % 3 ? "" : " Fizz "
Expanded version for the folks wanting to understand this version:
// We create a global variable `a` with an empty array on it:
// other global variable `i` is created with a value of 0:
// We loop while i is lower than 101 adding 1 to i each time:
// Per loop we push i to the array `a`, or the value of `f` + "Buzz"
a . push ( i % 5 ? f || i : f + " Buzz " )
// `f` is yet another global variable, this time with the "Fizz" part:
@ibrokemycomputer made another 62 characters version. This one includes a console.log
:
for ( i = 0 ; ++ i < 101 ; console . log ( i % 5 ? f || i : f + " Buzz " )) f = i % 3 ? "" : " Fizz "
Version with comments:
// Start a global `i` variable with `0`
// Every iteration we add `1` to `i` while it is lower than `101`
// `f` here actually comes from the "body" of this `for` loop.
// If `i` is not divisible by `5` we log `f`, and if is falsy we log `i`
// Otherwise we log `f` + "Buzz".
i % 5 ? f || i : f + " Buzz " ,
// The `f` global is set to an empty string if `i` is not divisible by `3`,
// and set to "Fizz" if it is.
User @battlecoder on X made this beauty:
a = [ i = 1 ]; while ( i < 100 ) a [ i ++ ] = ( i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i
Code with explanations:
// We create a global variable `a`
// This time we assign 1 to a global `i` inside the array `a`,
// so we initialize with the value 1 in index 0
// We use `while` this time
// And instead of using `push` we assign the `i++` value per loop
// This logic is pretty similar to the original algorithm shown above
( i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i ;
User @arekx made it to 60 characters! Here’s the snippet:
for ( a = [ i = 0 ]; i < 100 ;) a [ i ++ ] = ( i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i
And here’s the explanation:
// We create a global `a` and assign an array to it with the first item being `i = 0`
// This way we assign 0 to both `i` and to the first item of `a`.
// We loop while `i` is lower than `100`
// Every loop we assign to the global `a` in the position `i++`.
// `++` ads 1 to i but returns the current value, so the first iteration it will be 0
// Finally this logic is pretty sumular to previous approaches, we
// check `i % 3` for "Fizz" and `i % 5` for Buzz, or we return `i`
( i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i ;
User @posandu took one byte away from the previous winner by using type coercion in his favor. Here’s the snippet:
for ( a = i = []; i < 100 ;) a [ i ++ ] = ( i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i
Explained version:
// We create a global `a` and a `i`, and assign and empty array to both of them
// We loop while `i` is lower than `100`
// Every loop we assign to the global `a` in the position `i++`.
// `i` initially was `[]`, and when we add `1` to it, it becomes "1"
// and next time it will be `2`, `3` and so on.
// Finally this logic is pretty sumular to previous approaches, we
// check `i % 3` for "Fizz" and `i % 5` for Buzz, or we return `i`
( i % 3 ? "" : " Fizz " ) + ( i % 5 ? "" : " Buzz " ) || i ;