Fizz Buzz Implementations

Fizz Buzz is commonly used as an interview screening test for computer programmers. It is claimed in the blogsphere (see the references cited in the previous Wikipedia link) that demonstrating the ability to implement Fizz Buzz live is a trivial exercise for any competent developer. This is in spite of the fact that such a claim is often accompanied by anecdotal evidence that over half of experienced programmers applying for typical programming jobs need more than a trivial amount of time (say, more than five minutes) to implement a Fizz Buzz solution.

Why evidence about the difficulty of implementing Fizz Buzz can't be taken at face value is baffling to me. Instead, the blogsphere is full of arguments for why Fizz Buzz shows that most experienced programmers really can't program. That there are few truly competent programmers. And the ability to actually code anything is a skill reserved for the talented few.

But I see confirmation bias in this argument. I see elitism. I see a knee-jerk reluctance to question authority opinion or consensus. This is the kind of thing that shows programming is comprised of great artists rather than great engineers. And importantly, even if it is true that not many people can actually program, what does Fizz Buzz have to do with anything? Answer -- Nothing.

Just as there is no test that demonstrates programming competence, there is no test that demonstrates programming incompetence. Also, any trivial test is of trivial usefulness.

Let's demonstrate. For Fizz Buzz, the usual requirements are:

  • For a range of numbers (say, 1 to 100)
  • If the current number is divisible by 3, then print "Fizz"
  • If the current number is divisible by 5, then print "Buzz"
  • If the current number is divisible by both 3 and 5, then print "FizzBuzz"
  • Else, print the current number.

The most straightforward solution I can think of that satisfies these requirements would be (in, say, Python):


'''Straightforward Fizz Buzz implementation.'''
print 1
print 2
print "Fizz"
print 4
print "Buzz"
# You get the idea...
print 13
print 14
print "FizzBuzz"
print 16
# No need to go on...

I could type, cut and paste, and save the whole thing out in under five minutes. So the task is, in fact, trivial. Asking for a "standard code review" afterward would catch any typos.

However, I am almost certain this solution would be deemed by interviewers as trivial using a derogatory meaning of the word. They would ask me about the unstated requirements. There are always unstated requirements. It's called domain knowledge. I must know that the purpose of the Fizz Buzz test is to demonstrate being a competent programmer. Every competent programmer knows the tricks of the trade. I must use loops and conditional branching. I must show fluency in a particular computer language.

So next I would try implementing a meta-solution to Fizz Buzz (in, say, PHP):


<?php
// Fizz Buzz Meta-Implementation.
// Notice output is a Python program that implements Fizz Buzz
// as stupidly as possible.

for ($i = 1; $i <= 100; $i++) {
    $s = (string)$i;
    $outs = array($s, 'Fizz', 'Buzz', 'FizzBuzz'); 
      // efficiency deliberately shown to not be a requirement
    $token = 0; 
      // its final value will tell us to print Fizz, Buzz, 
      // FizzBuzz, or the loop index
    if (is_int($i/3)) {
        $token += 1;
    }
    if (is_int($i/5)) {
        $token += 2;
    }
    echo("print '" . $outs[$token] . "'\n");
}
?>

This actually took me more than five minutes, but it might be sufficiently original to impress an interviewer. Notice, among other things, that testing this solution is gratuitously difficult. First the PHP program would have to be run. Then the Python program.

Does the above solution show programming competence in any meaningful way? Of course not.

How about an implicit requirement that I implement a solution like I would implement a "real" program? In that case, I would immediately google a solution--probably trying StackOverflow first. In under five minutes, this yielded a beautiful solution that's potentially even a one-liner. However, it took more than five minutes just to type up and fix the typos. (Which, for this particular case, were all spelling errors.)


'''Fizz Buzz implementation. See Wikipedia entry for requirements.

Input: None
Output is one of: { loop_counter_value | Fizz | Buzz | FizzBuzz }

Tried to make the program as simple to understand as possible.
But did not try to hide from Python idiom.
So simple-to-understand != easy-to-understand necessarily.
Depends on familiarity with Python.

From snippet found on StackOverflow.

Basic idea is that divisibility can be calculated using modulo arithmetic.
That is, if x is divisible by y, then (not x % y) is true, else false.
Everything else is just Python tricks.

Validation and Verification: Inspected that results met requirements.

'''

# Range of numbers to determine FizzBuzz for:
smallest = 1
largest = 100

for i in range(smallest, largest + 1):
    print (not i % 3) * 'Fizz' + (not i % 5) * 'Buzz' or str(i)

All the comments are because real code is documented and my implicit requirement was to imitate real code. So does this demonstrate competence? No. What about the fact I took more than a trivial amount of time. More than five minutes. Is the above code outside the abilities of many programmers given sufficient time and knowledge of the basic idea described in the code's comments? No.

A crucial point is the trick about modulo arithmetic. A competent programmer could go their entire career, depending on their domain expertise, without every having to take the remainder of any number. Much less test it.

Having googled Fizz Buzz and seen various solutions in various languages, could I now implement a typical solution from memory in under five minutes in a language I haven't seen it implemented in? Here is the implementation I came up with in Go (golang).


package main

import (
 "fmt"
)

func main() {
 smallest := 1
 largest := 100
 for i := smallest; i < largest+1; i++ {
  fizz := i%3 == 0
  buzz := i%5 == 0
  if !(fizz || buzz) {
   fmt.Print(i)
  } else {
   if fizz {
    fmt.Print("Fizz")
   }
   if buzz {
    fmt.Print("Buzz")
   }
  }
  fmt.Println()
 }
}

No. The above took more than five minutes. Quite a bit more. I was not as familiar with the details of Go syntax as I thought I was. I cannot write more than a few lines of code without making some kind of mistake. I had to look up the command for automatic reformatting.

Finally, what if I reimplemented the above solution in a language I am very comfortable with? Say, C++?


#include <iostream>
using namespace std;

int main() {
 int smallest = 1;
 int largest = 100;

 bool fizz;
 bool buzz;

 for (int i = smallest; i < largest+1; i++) {
  fizz = i % 3 == 0;
  buzz = i % 5 == 0;
  if (!(fizz || buzz)) {
   cout << i;
  } else {
   if (fizz) {
    cout << "Fizz";
   }
   if (buzz) {
    cout << "Buzz";
   }
  }
        cout << endl;
 }
}

Yes. I could essentially copy the solution from Go to C++ in under five minutes. Does this demonstrate I am a competent programmer? No.

In conclusion, despite the seeming consensus of expert programmer/bloggers, Fizz Buzz is NOT a trivial exercise for any competent programmer. It is a tenable belief that there are no trivial tests for either competency or incompentency. The evidence about Fizz Buzz can be taken at face value. I would never require an interviewee to implement Fizz Buzz.

No comments:

Post a Comment