DEV Community

Cover image for [Challenge] 🐝 FizzBuzz without if/else
Keff
Keff

Posted on β€’ Edited on

38 9

[Challenge] 🐝 FizzBuzz without if/else

This challenge is intended for Javascript, but you can complete it with any language you like and can.


Most of us will know the FizzBuzz game/exercise and probably have done it many times. It should be a simple and straightforward exercise for most developers...

BUT can you do it without using if/else statements?


Challenge Description

Write a program that outputs the string representation of numbers from 1 to N.

But for multiples of 3, it should output "Fizz" instead of the number and for the multiples of 5 output "Buzz". For numbers which are multiples of both 3 and 5, you should output "FizzBuzz".

Curveball: You must not use if/else statements, and ideally, no ternary operator.

Example:

const n = 15;

/* 
Return:
  [
    "1",
    "2",
    "Fizz",
    "4",
    "Buzz",
    "Fizz",
    "7",
    "8",
    "Fizz",
    "Buzz",
    "11",
    "Fizz",
    "13",
    "14",
    "FizzBuzz"
  ]
*/
Enter fullscreen mode Exit fullscreen mode

I will comment my solution in a couple of days.

πŸ’ͺ Best of luck! πŸ’ͺ


Credits:
Cover Image from https://codenewbiesite.wordpress.com/2017/01/29/fizz-buzz/

Top comments (93)

Collapse
 
stephanie profile image
Stephanie Handsteiner β€’ β€’ Edited

Easy, just do it in CSS.

ol {
    list-style-type: inside;
}

li:nth-child(3n), li:nth-child(5n) {
    list-style-type: none;
}

li:nth-child(3n):before {
    content: 'Fizz';
}

li:nth-child(5n):after {
    content: 'Buzz';
}
Enter fullscreen mode Exit fullscreen mode

Needs some Markup to display obviously.

Collapse
 
ben profile image
Ben Halpern β€’

Ha!

Collapse
 
nombrekeff profile image
Keff β€’

Magnificent! I knew there were going to be really neat solutions!!

Thanks for sharing your solution πŸ’ͺ

Collapse
 
rushsteve1 profile image
Steven vanZyl β€’

The cleanest and best FizzBuzz implementation I know of doesn't use any if statements at all. Actually it doesn't use any control flow at all in most languages.
The approach is fully described here: philcrissman.net/posts/eulers-fizz...

On my Repl.it I also have this same approach implemented in several other languages:
repl.it/@rushsteve1/

Collapse
 
coreyja profile image
Corey Alexander β€’

This was great! Love it when there is a simple probable mathematic solution to these kinds of things!

Collapse
 
nombrekeff profile image
Keff β€’

Me too, so clean! I love maths but I'm crap at it myself xD

Collapse
 
nombrekeff profile image
Keff β€’

I did not know about this, thanks for sharing. I will remember this!

Collapse
 
agtoever profile image
agtoever β€’ β€’ Edited

Holy sh*t, my other solution was really ugly! :-o
Here is a (much) better one (also in Python3):

def fizzbuzz(n):
    for i in range(1, n + 1):
        print([f'{i}', f'Fizz', f'Buzz', f'FizzBuzz'][(i % 3 == 0) + 2 * (i % 5 == 0)])

fizzbuzz(22)

This works using the property that True in Python has numerical value 1 and using f-strings in an array. The proper element in the array is chosen based on the mentioned property, checking for divisibility with 3 and 5.

Collapse
 
nastyox1 profile image
nastyox β€’ β€’ Edited

logical operators

The second half of an "and" statement only evaluates if the first half is true.

for(var i = 1; i < 100; i++){
    !(i % 3) && document.write("fizz");
    !(i % 5) && document.write("buzz");
    i % 3 && i % 5 && document.write(i);
    document.write(" ");
}

...

for loops

For loops check your second declaration on each iteration. Force it to be false on the second iteration, and you've got something that'll check your condition a single time.

for(var i = 1; i < 100; i++){
    for(var j = 0; !j && !(i % 3); j++) document.write("fizz");
    for(var j = 0; !j && !(i % 5); j++) document.write("buzz");
    for(var j = 0; !j && i % 3 && i % 5; j++) document.write(i);
    document.write(" ");
}

...

arrays

Referencing an index that that exists gives you the value stored there, but referencing an index that doesn't exist gives you undefined. Use an "or" statement to give yourself a fallback value when this happens, and you'll be ready to go.

var fizz = ["fizz"], buzz = ["buzz"];
for(var i = 1; i < 100; i++) document.write((((fizz[i % 3] || "") + (buzz[i % 5] || "")) || i) + " ");

Or, fill an array with your options, and leverage the fact that true can be used as 1 in JavaScript to do some index-selection math.

var arr = [null, "fizz", "buzz", "fizzbuzz"];
for(var i = 1; i < 100; i++){
    arr[0] = i;
    document.write(arr[!(i % 3) + !(i % 5) * 2] + " ");
}

...

try/catch blocks

You can purposefully throw exceptions when a boolean is false by referencing a variable that doesn't exist (the "throwException" variable in this case).

function tryIf(test, pass, fail){
    try{
        !test || throwException;
        (fail || function(){})();
    }
    catch(e){
        pass();
    }
}

for(var i = 1; i < 100; i++){
    tryIf(!(i % 3), function(){
        document.write("fizz");
    });

    tryIf(!(i % 5), function(){
        document.write("buzz");
    });

    tryIf(i % 3 && i % 5, function(){
        document.write(i);
    });

    document.write(" ");
}

...

while loops

This is the same concept as for loops. Force the loop to stop after one iteration (this time with a break), and you've got something that'll check your condition a single time.

for(var i = 1; i < 100; i++){
    while(!(i % 3)){
        document.write("fizz");
        break;
    }

    while(!(i % 5)){
        document.write("buzz");
        break;
    }

    while(i % 3 && i % 5){
        document.write(i);
        break;
    }

    document.write(" ");
}

...

switch statements

Who could forget the classic alternative to if statements? Technically not even cheating!

for(var i = 1; i < 100; i++){
    switch(i % 3){
        case 0:
            document.write("fizz");
        default:
    }

    switch(i % 5){
        case 0:
            document.write("buzz");
        default:
    }

    switch(!(i % 3 && i % 5)){
        case false:
            document.write(i);
        default:
    }

    document.write(" ");
}
Collapse
 
nombrekeff profile image
Keff β€’

Wow, those are some solutions right there! Thanks a lot for sharing and taking the time to explain it.

I did some silly stuff, just for fun lol:

function fizzBuzz(number = 100) {
    let current = 1;
    let string = '';

    while (current <= number) {
        string += current + ' ';
        current += 1;
    }

    string = string.trim()
        .replace(/[0-9]+/g, (match) => {
            const valueMap = ['FizzBuzz', match];
            const index = match % 15;
            return valueMap[index] || match;
        })
        .replace(/[0-9]+/g, (match) => {
            const valueMap = ['Fizz', match];
            const index = match % 3;
            return valueMap[index] || match;
        })
        .replace(/[0-9]+/g, (match) => {
            const valueMap = ['Buzz', match];
            const index = match % 5;
            return valueMap[index] || match;
        })

    return string.split(' ');
}
Collapse
 
rad_val_ profile image
Valentin Radu β€’

Here's the simplest I can think of without any statements. πŸ™ƒ

function run(n, i=1, j=1, k=1, acc=[]) {
  !j && k && acc.push('fizz')
  !k && j && acc.push('buzz')
  !k && !j && acc.push('fizzbuzz')
  k && j && acc.push(i)

    n - 1 && run(n - 1, i + 1, (j + 1) % 3, (k + 1) % 5, acc)
  return acc
}

console.log(run(30))
Collapse
 
nombrekeff profile image
Keff β€’

Nice, recursion for the win πŸ’ͺ

Collapse
 
nombrekeff profile image
Keff β€’

Thanks for sharing!

Collapse
 
vonheikemen profile image
Heiker β€’ β€’ Edited

You can still have flow control with functions.

const troo = (iff, elz) => iff;
const falz = (iff, elz) => elz;
const choose = (value) => [falz, troo][Number(Boolean(value))];

const is_fizz = (n) => choose(n % 3 === 0);
const is_buzz = (n) => choose(n % 5 === 0);

const fizzbuzz = (n) =>
  is_fizz(n) (
    () => is_buzz (n) ("FizzBuzz", "Fizz"),
    () => is_buzz (n) ("Buzz", n),
  )
    .call();

const range = (end) =>
  new Array(end).fill(null).map((val, index) => index + 1);

range(15).map(fizzbuzz).join(", ");
Collapse
 
nombrekeff profile image
Keff β€’

I liked this approach! Thanks for sharing!

Collapse
 
ehsan profile image
Ehsan Azizi β€’ β€’ Edited

Here is an ugly solution in one line

for (let i = 1; i <= number; i++) {
  console.log((i % 3 === 0 && i % 5 === 0 && 'fizzbuzz') || (i % 3 === 0 && 'fizz') || (i % 5 === 0 && 'buzz') || i);
}
Collapse
 
shravan20 profile image
Shravan Kumar B β€’

U aren't supposed to use Ternary Operator.

Collapse
 
ehsan profile image
Ehsan Azizi β€’ β€’ Edited

Oh yeah! didn't notice that, I have updated my solution

Collapse
 
mintypt profile image
mintyPT β€’

Here is some python for you :)

print([
  (not (i % 3) and not (i % 5) and "FizzBuzz") or
  (not (i % 3) and "Fizz") or
  (not (i % 5) and "Buzz") or
  i
  for i in range(1,16)])
Collapse
 
jpantunes profile image
JP Antunes β€’

There was a similar and equally really good thread about a month ago that had some devilishly clever solutions... highly recommend it!

My contributions below:

//1
const fizzBuzz = n => {
    const mapper = (arr, modulo, txt) => arr
                                    .filter(e => e % modulo == 0)
                                    .forEach(e => arr[arr.indexOf(e)] = txt);
    let x = 1;
    const range = [...Array(n)].map(_ => x++)
    mapper(range, 15, 'FizzBuzz');
    mapper(range, 5, 'Buzz');
    mapper(range, 3, 'Fizz');
    return range.toString();
}

//2
const fizzBuzz = n => {
    let x = 1;
    const range = [...Array(n)].map(_ => x++);
    for (let i = 2; i <= n; i += 3) range[i] = 'Fizz';
    for (let i = 4; i <= n; i += 5) range[i] = 'Buzz';
    for (let i = 14; i <= n; i += 15) range[i] = 'FizzBuzz';
    return range.toString();
}

//3
const fizzBuzz = n => {
    const isFizzBuzz = n => ( {false: '', true: 'Fizz'}[n % 3 == 0] 
                            + {false: '', true: 'Buzz'}[n % 5 == 0] 
                            || n.toString() );
    let x = 1;
    return [...Array(n)].map(_ => isFizzBuzz(x++)).toString();                             
}

//4 ...originally from a Kevlin Henney presentation here: https://youtu.be/FyCYva9DhsI?t=1191
const fizzBuzz = n => {
  const test = (d, s, x) => n % d == 0 ? _ => s + x('') : x;
  const fizz = x => test(3, 'Fizz', x);
  const buzz = x => test(5, 'Buzz', x);
  return fizz(buzz(x => x))(n.toString());
}
Collapse
 
nombrekeff profile image
Keff β€’

Nice stuff. I will be checking out the thread!

There have been some really clever solutions posted here as well.

Collapse
 
shravan20 profile image
Shravan Kumar B β€’ β€’ Edited
function fizzBuzz(n){
   let arr = [ ];
   for(i=1 ; i<=n; i++){
      let flag = i%15==0 && arr.push('FizzBuzz') || i%5==0 && arr.push('Buzz') || i%3==0 && arr.push('Fizz');
      !flag && arr.push(i);
   }

 return arr;
}



console.log(fizzBuzz(15));

Manolo Edge
@nombrekeff

Image of Docusign

πŸ› οΈ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more