A silly bug#

FizzBuzz#

Rules#

Count from 1 to 100

  • If divisible by 3, print “Fizz”

  • If divisible by 5, print “Buzz”

  • If divisible by 15, print “FizzBuzz”

  • Otherwise, print the number

First implementation#

const fizzBuzz = (i: number): string => {
  if (i % 15 === 0) {
    return "fizzbuzz";
  }
  if (i % 3 === 0) {
    return "fizz";
  }
  if (i % 5 === 0) {
    return "buzz";
  }
  return i.toString(10);
};

Quick! Where is the bug?

Well, let’s write a main and run it:

const main = () => {
  for (let i = 1; i <= 30; i++) {
    console.log(fizzBuzz(i));
  }
};

main();

This gives:

1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizz
16
17
fizz
19
buzz
fizz
22
23
fizz
buzz
26
fizz
28
29
fizz

Surely, something is wrong : we never see “fizzbuzz” in the output !

Fixing the bug#

By reading the code carefully, we can see that the bug occurs if the number is divisible by both 3 and 5.

We get through the first if first, and return early.

There are many ways to fix the code, one solution is to move the if (number % 15 === 0) first:

export const fizzBuzz = (i: number): string => {
  if (i % 15 === 0) {
    return "fizzbuzz";
  }
  if (i % 3 === 0) {
    return "fizz";
  }
  if (i % 5 === 0) {
    return "buzz";
  }
  return i.toString(10);
};

Writing some tests#

Writing a main and checking the output by hand is not fun, so let’s write some tests instead:

import { fizzBuzz } from "./fizzbuzz.ts";
import { assertEquals } from "@std/assert";

Deno.test("Print 'fizz' when divisible by 3", () => {
  assertEquals(fizzBuzz(3), "fizz");
  assertEquals(fizzBuzz(6), "fizz");
  assertEquals(fizzBuzz(9), "fizz");
});

Deno.test("Print 'buzz' when divisible by 5", () => {
  assertEquals(fizzBuzz(5), "buzz");
  assertEquals(fizzBuzz(10), "buzz");
  assertEquals(fizzBuzz(20), "buzz");
});

Deno.test("Print 'fizzbuzz' when divisible by 15", () => {
  assertEquals(fizzBuzz(15), "fizzbuzz");
  assertEquals(fizzBuzz(30), "fizzbuzz");
});

Deno.test("Print number otherwise", () => {
  assertEquals(fizzBuzz(2), "2");
  assertEquals(fizzBuzz(4), "4");
});

Running the tests#

$ deno test fizzbuzz_test.ts

Check fizzbuzz_test.ts
running 4 tests from ./fizzbuzz_test.ts
Print 'fizz' when divisible by 3 ... ok
Print 'buzz' when divisible by 5 ... ok
Print 'fizzbuzz' when divisible by 15 ... ok
Print number otherwise ... ok

ok | 4 passed | 0 failed (4ms)