24 September 2023

What does your FizzBuzz say about you?

A classic problem

At the interview for my first job, I was asked to write a FizzBuzz. A FizzBuzz is a program that prints a series of numbers, unless a number is divisible by 3, in which case it prints Fizz, or divisible by 5, in which case it prints Buzz. For any numbers divisible by both, it should print FizzBuzz.

My answer was some pseudocode along the following lines:

// Pseudocode
for (int i = 1; i <= 100; i++) {
    if (i % 15 == 0) {
        println("FizzBuzz");
    } else if (i % 5 == 0) {
        println("Buzz");
    } else if (i % 3 == 0) {
        println("Fizz");
    } else {
        println(i);
    }
}

Which is quite close to Java:

// Java
public class Main {
    public static void main(String[] args) {
        for (int i = 1; i <= 100; i++) {
            if (i % 15 == 0) {
                System.out.println("FizzBuzz");
            } else if (i % 5 == 0) {
                System.out.println("Buzz");
            } else if (i % 3 == 0) {
                System.out.println("Fizz");
            } else {
                System.out.println(i);
            }
        }
    }
}

And also pretty close to C:

/* C */
#include <stdio.h>
void main() {
    for (int i = 1; i <= 100; i++) {
        if (i % 15 == 0) {
            printf("FizzBuzz");
        } else if (i % 5 == 0) {
            printf("Buzz");
        } else if (i % 3 == 0) {
            printf("Fizz");
        } else {
            printf("%d", i);
        }
        printf("\n");
    }
}

What can we tell about someone from the FizzBuzz they write?

Obviously, if they fail to write one at all, that's a pretty strong indicator that they aren't an ideal hire for a role which requires programming.

But there are many ways to solve this trivial task, and the programmer's particular choice of approach gives a few clues about how their interests, habits, and "code philosophy".

Do they pick a slightly more esoteric language?

-- Haskell

fizzBuzzValue n
  | multipleOf 15 = "FizzBuzz"
  | multipleOf 3 = "Fizz"
  | multipleOf 5 = "Buzz"
  | multipleOf 1 = show n
  where multipleOf = (0==) . rem n

-- map over numbers 1 to 100 and output fizzBuzzValue for each
main = mapM (putStrLn . fizzBuzzValue) [1..100]

Do they write something terse and code-golfed?

-- Haskell
main=mapM(putStrLn.f)[1..100]
f n|y 15="FizzBuzz"|y 3="Fizz"|y 5="Buzz"|y 1=show n where y=(0==).rem n

Or something that is easier to digest?

# Python
for x in range(1, 100):
    if x % 15 == 0:
        print("FizzBuzz")
    elif x % 5 == 0:
        print("Buzz")
    elif x % 3 == 0:
        print("Fizz")
    else:
        print(x)

Maybe they want to avoid printing "FizzBuzz", instead printing "Fizz" followed by "Buzz"?

# Python
for x in range(1, 100):
    if x % 3 == 0:
        print("Fizz", end='')
    if x % 5 == 0:
        print("Buzz", end='')
    if x % 5 != 0 and x % 3 != 0:
        print(x, end='')
    print()

Perhaps they don't want to repeat the print statement either:

// Go
package main
import "fmt"
func main() {
    for i := 1; i <= 100; i++ {
        x := ""
        if i % 3 == 0 {
            x = "Fizz"
        }
        if i % 5 == 0 {
            x += "Buzz"
        }
        if x == "" {
            x = fmt.Sprintf("%d", i)
        }
        fmt.Println(x)
    }
}

Do they write something they think is clever (and DRY!), but is actually rather harder to read?

// JavaScript
for (let x = 1; x <= 100; x++) {
    const div5 = !(x % 5);
    const div3 = !(x % 3);
    console.log(
        (div3 || div5)
        ? (div3 ? "Fizz" : "") + (div5 ? "Buzz" : "")
        : String(x)
    );
}

Or something clearer, but with some avoidable repetition?

; Scheme
(do ((i 1 (+ i 1))) ((= i 100))
  (display
    (cond
      ((zero? (remainder i 15)) "FizzBuzz")
      ((zero? (remainder i 5)) "Buzz")
      ((zero? (remainder i 3)) "Fizz")
      (else i)))
  (newline))
... Bonus: Scheme, but in a more imperative style.
(do ((i 1 (+ i 1))) ((= i 100))
  (when (zero? (remainder i 3))
    (display "Fizz"))
  (when (zero? (remainder i 5))
    (display "Buzz"))
  (when (and
          (positive? (remainder i 3))
          (positive? (remainder i 5)))
    (display i))
  (newline))

Whatever they do, I hope they don't do this!


[+] A note for language-zealots.

This isn't really a comment on the languages themselves.

The Go example could just as easily have been written in JavaScript (But the JavaScript one could not have been written in Go).

// JavaScript
for (let i = 1; i <= 100; i++) {
   let x = "";
   if (i % 3 === 0) {
       x = "Fizz";
   }
   if (i % 5 === 0) {
       x += "Buzz";
   }
   if (x === "") {
       x = String(i);
   }
   console.log(x);
}
Tags: Tech