Experimenting with FizzBuzz

Experimenting with FizzBuzz

The FizzBuzz is a game for children to teach them about division. It has been (and still is) used in programming interviews sort out the bad programmers.

The rules are simple:

  • You count from 1 to 100.
  • When it's a multiple of 3, write Fizz.
  • When it's a multiple of 5, write Buzz.
  • When it's a multiple of 3 and five, write FizzBuzz.
  • When none of the rules applies, write the number.

It plays with the basic concepts of programming, operators, conditions and loops.

I'll detail over here the process I'll go through to make it work. One first simple and dumb version could go as such :

let i = 0;

while(++i <= 100) {
  if (i % 3 === 0 && i % 5 === 0) {
    document.write('FizzBuzz<br/>');
  }
  else if (i % 3 === 0) {
    document.write('Fizz<br/>');
  }
  else if (i % 5 === 0) {
    document.write('Buzz<br/>');
  }
  else {
    document.write(`${i}<br/>`);
  }
}

Problem solved, and yet it can already be re-factored to this with the usage of variables, concatenation and functions :

const println = txt => document.write(`${txt}<br/>`);
const isMultipleOf = (n, p) => n % p === 0;

let i = 0;

while(++i <= 100) {
  const multipleOf3 = isMultipleOf(i, 3);
  const multipleOf5 = isMultipleOf(i, 5);
  let displayedText = '';
  if (multipleOf3) {
    displayedText += 'Fizz';
  }
  if (multipleOf5) {
    displayedText += 'Buzz';
  }
  println(displayedText.length > 0 ? displayedText : i);
}

And then, your boss enters the room, and ask if you can manage multiple of 7 and 9 with "foo" and "bar".

You could add some more variables and more if statements but you know you can do better. So you create a function which takes in the numbers you want to work with and returns an array of elements.

const isMultiple = (n, p) => n % p === 0;

const testRules = (rules, i) => rules
  .map(([n, text]) => [isMultiple(i, n), text])
  .filter(([multiple]) => multiple)
  .reduce((acc, [, text]) => acc += text, '');

const FizzBuzz = (rules = {3: 'Fizz', 5: 'Buzz'}) => {
  const rulesArray = Object.entries(rules);
  return output = new Array(100)
	  .fill(0)
	  .map((v, i) => testRules(rulesArray, ++i) || i);
}

document.write(FizzBuzz({3: 'Fizz', 5: 'Buzz', 7: 'Foo', 9: 'Bar'}).join('<br/>'));

This adds a functional approach to the problem and shows some more skills.

Finally if shortness is what you want, you can go one-liner this way :

for(i=0;i<100;)document.write(((++i%3?"":"Fizz")+(i%5?"":"Buzz")+(i%7?"":"Foo")+(i%9?"":"Bar")||i) + '<br/>'); 

Much harder to read/understand if you're not into JavaScript, but it shows a good knowledge of the language tricky bits.