DEV Community

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

Posted on • Updated on

[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/

Latest comments (93)

 
nombrekeff profile image
Keff

Pretty interesting cheers! I recall using it on the CLI at some point, but without actually knowing it was a language!

 
nombrekeff profile image
Keff

That's pretty neat! It reminds my a bit of rust's match. What was/is awk usually used for?

Collapse
 
nombrekeff profile image
Keff

Nice, I have heard about it but never saw any writen code for awk!!

Collapse
 
dannyengelman profile image
Danny Engelman

Bit late to the party...

let arr = Array(100)
  .fill({ three: "Fizz", five: "Buzz" })
  .map(( {three,five}, idx) => {
    idx++;
    if (idx % 15 == 0) return three + five;
    if (idx % 3 == 0) return three;
    if (idx % 5 == 0) return five;
    return idx;
  });
console.log(arr);
Enter fullscreen mode Exit fullscreen mode
  • maintainable
  • extendible
  • translatable
  • performant
Collapse
 
issammani profile image
Issam Mani • Edited

A bit late to the party but here is my take. I'm basically substituting cond ? valueWhenTrue : valueWhenFalse for a logical equivalent (cond && valueWhenTrue) || valueWhenFalse + calling the function recursively.
Note: array returned is in reverse order ! But we can easily solve that with .reverse()

const fizzBuzz = (num,acc = []) => {
    acc.push(
        (num % 15 === 0 && 'FizzBuzz' ||
          (num % 3 === 0 && 'Fizz' || 
            (num % 5 === 0 && 'Buzz' || 
              num
            )
          )
        )
    )
    return (num === 1 && acc) || fizzBuzz(num - 1,acc);
};


console.log(fizzBuzz(15));
Enter fullscreen mode Exit fullscreen mode
Collapse
 
guillaume_agile profile image
craft Softwr & Music • Edited

Here's my proposal for a non if/else implementation
Using only Types and Abstractions (Interface) and a bit a Linq (C#)
But the most important part is using full polymorphism and a DDD style with immutable objects (structs)
Made with strict TDD (all tests green), please check my repo

  public class FizzBuzz
    {
        private readonly IDictionary<int, string> rulesSet;
        public FizzBuzz()
        {        
          rulesSet = new Dictionary<int, string>();
            rulesSet.Add(3, "Fizz");
            rulesSet.Add(5, "Buzz");
            rulesSet.Add(7, "Wizz");          
        }

        public string Process(int value)
        {               
            IResult res = new VoidResult();
            foreach (var element in rulesSet.Where(element => value % element.Key == 0))
            {
                res = new TempResult(res.Result + element.Value);
            }
            res = res.Finalize(value.ToString());
            return res.Result;
        } 
     }

    public interface IResult
    {
        string Result { get; }

        IResult Finalize(string v);
    }

    public struct VoidResult : IResult
    {
        public string Result => string.Empty;

        public IResult Finalize(string v)
        {
            return new FinalResult(v);
        }
    }

    public struct TempResult : IResult
    {
        readonly string value;

        public TempResult(string value)
        {
            this.value = value;
        }

        public string Result => value;

        public IResult Finalize(string v)
        {
            return new FinalResult(this.value);
        }
    }

    public struct FinalResult : IResult
    {
        readonly string v;

        public FinalResult(string v)
        {
            this.v = v;
        }

        public string Result => v;

        public IResult Finalize(string v)
        {
            throw new System.NotSupportedException("cannot finalize what is already finalyzed");
        }
    }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
guillaume_agile profile image
craft Softwr & Music

My 10 cents:
you should have said: FizzBuzz with a Cyclomatic Complexity to maximum 2 (or 1).
Because if you replace a if/else by Logical Operators, or Switch or While or For, you aren't doing better code in terms of Cyclomatic Complexity

The CSS approach is one of the most elegant.
Another one without any cyclomatic complexity is acheived with a strong type system, like what you can do in Haskell, F#; Kotlin or TypeScript
See that solution (not mine, but clever if you understand the type inference mecanism) gist.github.com/na-o-ys/34e9ebf7fc...

Collapse
 
martis347 profile image
Martynas Kan

Really nice idea!

Here's how I did it 😁

const fizzBuzz = (number) => {
    const array = Array(number).fill(undefined).map((_, index) => index + 1);
    const fiz = array.filter(v => !(v % 3))
    const baz = array.filter(v => !(v % 5))
    const fizBaz = array.filter(v => !(v % 5) && !(v % 3))

    let result = {};
    for (let i of array) {
        result[i] = i;
    }
    for (let f of fiz) {
        result[f] = 'Fizz';
    }
    for (let b of baz) {
        result[b] = 'Buzz';
    }
    for (let fb of fizBaz) {
        result[fb] = 'FizzBuzz';
    }

    return Object.values(result);
}
Collapse
 
nombrekeff profile image
Keff

Glad you liked it!

I just published a new challenge if you want another one :)

Collapse
 
wdhowe profile image
wdhowe

One of the ways in Clojure:

(defn divisible?
  "Determine if a number is divisible by the divisor with no remainders."
  [div num]
  (zero? (mod num div)))

(defn fizz-buzz
  "Fizz if divisible by 3, Buzz if divisible by 5, FizzBuzz if div by both, n if neither."
  [n]
  (cond-> nil ; threaded value starts with nil (falsey)
    (divisible? 3 n) (str "Fizz") ; if true, adds Fizz to the threaded value (nil)
    (divisible? 5 n) (str "Buzz") ; if true, adds Buzz to the threaded value (nil or Fizz)
    :always-true     (or n))) ; return the threaded value if not nil (Fizz/Buzz) or n

(let [start 1
      stop 20]
  (println "FizzBuzz:" start "-" stop)
  (doseq [x (range start (+ 1 stop))] (println (fizz-buzz x))))

Original idea seen here: clojuredocs.org/clojure.core/cond-...

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

Collapse
 
nacasha profile image
Izal Fathoni

My approach is to take advantage of string replace 🤣️

const n = 15;

for (let i = 1; i <= n; i++) {
  const fizz = ['Fizz'][i % 3];
  const buzz = ['Buzz'][i % 5];

  const value = `${fizz}${buzz}`
    .replace('undefinedundefined', i)
    .replace('undefined', '');

  console.log(value);
}
Collapse
 
nombrekeff profile image
Keff

Smart!

Collapse
 
imjoseangel profile image
Jose Angel Munoz

Here you have in Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import (division, absolute_import, print_function,
                        unicode_literals)


class FizzBuzz:
    def __init__(self):
        self.fizzbuzz = dict()

        for num in range(3, 101, 3):
            self.fizzbuzz[num] = "Fizz"

        for num in range(5, 101, 5):
            self.fizzbuzz[num] = "Buzz"

        for num in range(15, 101, 15):
            self.fizzbuzz[num] = "FizzBuzz"

        self.run()

    def run(self):

        for number in range(1, 101):
            print(self.fizzbuzz.get(number, number))


def main():

    FizzBuzz()


if __name__ == '__main__':
    main()
Enter fullscreen mode Exit fullscreen mode
Collapse
 
edkb profile image
Eduardo Binotto

Maybe we could have it ready from the DB. I know CASE / WHEN / THEM is sql if / else equivalent, but nobody tried yet, so here he go

SELECT
    CASE
        WHEN gs % 15 = 0
            THEN 'FizzBuzz'
        WHEN gs % 3 = 0
            THEN 'Fizz'
        WHEN gs % 5 = 0
            THEN 'Buzz'
        ELSE gs::text
    END
FROM
    generate_series(1,15) as gs;

Collapse
 
martinsebastian profile image
Martin Sebastian • Edited
const fizzBuzz = (until) => {
      const fizz = ["Fizz", "", ""];
      const buzz = ["Buzz", "", "", "", ""];

      (function fizzybuzzy(current) {
         console.log(fizz[current % 3] + buzz[current % 5]  || current);

         return (current + 1 <= until) && fizzybuzzy(current + 1);
     })(0);
}

fizzBuzz(100);
Collapse
 
martinsebastian profile image
Martin Sebastian

Also thinking about overriding Number.prototype.toString makes a fun thingy. Maybe someone already did, but someone for sure should :D

Collapse
 
martinsebastian profile image
Martin Sebastian • Edited

Some improvement to my earlier version.

A) better (arguably, because way more cognitive load than the very simple one above)

const fizzBuzz = (until, current = 0, fizzbuzz = ["", "Fizz", "Buzz"]) => {
    const fizzybuzzy = () => fizzbuzz[!(current % 3) * 1] + fizzbuzz[!(current % 5) * 2]  || current;
    return (current + 1 <= until) && (console.log(fizzybuzzy()), fizzBuzz(until, current + 1));
}

fizzBuzz(100);

B) above one as 1 liner b/c hello perl

const devBuzz = (function i(u, c= 0, m=["", "dev", ".to"])  {(c+1<=u) && (console.log(m[!(c % 3)*1] + m[!(c%5)*2] || c), i(u,c+1));});

devBuzz(20);
Collapse
 
faycelbouamoud profile image
faycelbouamoud

Very stupid solution ! but this is the first thing that comes to my mind !

const N = 15;
const arr = new Array(15).fill(null).map((el, index) => index + 1);

function forStep(arr, init, step, word) {
  const arrCopy = [...arr];
  for (let i = init - 1; i < N; i = i + step) {
    arrCopy[i] = word;
  }

  return arrCopy
}

function fizzbuzz() {
  const arrCop = forStep(forStep(forStep(arr, 3, 3, "fizz"), 5, 5, "buzz"), 15, 15, "fizzbuzz");
  console.log(arrCop);
}

fizzbuzz();