13brane's holidazed cavalcade of code shenanigans: the flavors of FizzBuzz - Days 1-8

 

(Full source code for the entire series will be progressively published here, and the other days of the cavalcade are here: day 0, 9-16, 17-24)

The FizzBuzz cavalcade started with eight procedural solutions to the problem. In none of these does the code make use of anything you wouldn’t be able to code with relative ease in C or even Assembly.

Simple, “straight out of college” level procedural code.

Day 1

The no BS, competent junior dev approach.

package day01

import "fmt"

func FizzBuzz(n int) string {
	if n%3 == 0 && n%5 == 0 {
		return "fizzbuzz"
	} else if n%3 == 0 {
		return "fizz"
	} else if n%5 == 0 {
		return "buzz"
	} else {
		return fmt.Sprint(n)
	}
}

This is what you would write on your first class about flow control. Nothing special about this, just honest, straightforward code. There are a couple of ways in which this can improve, but in college you’ll still get a good grade for it. In corporate, no one cares as long as the spec validates it (and the profiler says this code is not running 90% of the execution time).

It does translate the spec directly, though, so this is one of the more “understandable” versions.

Day 2

CompSci 101: Structured Programming (Good student version).

package day02

import "fmt"

func FizzBuzz(n int) string {
	var divBy3 bool = n%3 == 0
	var divBy5 bool = n%5 == 0
	var out string = ""

	if divBy3 {
		out = out + "fizz"
	}

	if divBy5 {
		out = out + "buzz"
	}

	if len(out) == 0 {
		out = fmt.Sprint(n)
	}

	return out
}

Single entry point: check.
Single exit point: check.
No use of goto: check.

Bonus points for setting up all variables and constraints right at the start. It’s still not optimal from an execution standpoint, as it uses 3 conditions (the problem can be solved “normally” with only two per execution path), but it’s still better than the previous version in that sense.

Spec translation is not as direct here, but it is still very easy to grok because the code path doesn’t branch in crazy ways. The state checking at the end is kind of lame, though (and it’s the extra, unneeded if).

Day 3

CompSci 101: (Un)Structured Programming (Bad student version).

package day03

import "fmt"

var divBy3 bool
var by5 bool
var out string
var flag bool

func FizzBuzz(n int) string {
	// clean variable
	divBy3 = false
	by5 = false
	out = ""
	flag = false

	divBy3 = n%3 == 0
	by5 = n%5 == 0

	if divBy3 {
		out = out + "fizz"
		flag = true
	}

	if by5 {
		out = out + "buzz"
		flag = true
	}

	if !flag {
		out = fmt.Sprint(n)
	}

	return out
}

This was clearly pilfered from the good student, with some things jumbled around and deliberately muffled for plausible deniability.

The TA wonders how this even compiles, then remembers that the tests were given as part of the statement of the assignment. The true ode to BDD. Wants to grade it a at zero, but plausible deniability is too strong. It even has typos in the only comment it got. No worries, this person will eventually switch majors to something more in line with their level of competence. Probably business administration or project management.

Day 4

Advanced student. Understands separation of concerns and subroutines. Wants to learn C++ one day, and will use every single fucking feature the language has to offer, making trivial code non trivial because “juniors need to be exposed to a wide variety of programming styles to become proficient”.

package day04

import "fmt"

func FizzBuzz(n int) string {
	var out string = ""

	if divBy3(n) {
		out = out + "fizz"
	}

	if divBy5(n) {
		out = out + "buzz"
	}

	if len(out) == 0 {
		out = fmt.Sprint(n)
	}

	return out
}

func divBy3(n int) bool {
	return n%3 == 0
}

func divBy5(n int) bool {
	return n%5 == 0
}

Could be worse.

Day 5

“Advanceder” student. Really understands subroutines and uses this knowledge to stay DRY. At the obvious cost of readability, of course.

package day05

import "fmt"

func FizzBuzz(n int) string {
	var out string = ""

	if divBy(n, 3) {
		out = out + "fizz"
	}

	if divBy(n, 5) {
		out = out + "buzz"
	}

	if len(out) == 0 {
		out = fmt.Sprint(n)
	}

	return out
}

func divBy(n, d int) bool {
	return n%d == 0
}

Day 6

Sophomore student. Basics of programming forever engraved in neocortex. Fully grasps SP, but has grown past that. Once read an article online called “Else considered harmful”. Only writes code in “early-exit” style since. Reads cat-v.org, uses VoidLinux and suckless tools as much as possible.

package day06

import "fmt"

func FizzBuzz(n int) string {
	if n%3 == 0 && n%5 == 0 {
		return "fizzbuzz"
	}

	if n%3 == 0 {
		return "fizz"
	}

	if n%5 == 0 {
		return "buzz"
	}

	return fmt.Sprint(n)
}

Day 7

Girlfriend of previous student. They study together, but she’s not been brainwashed yet. Cares more about code performance and good grades.

package day07

import "fmt"

func FizzBuzz(n int) string {
	if n%3 == 0 {

		if n%5 == 0 {
			return "fizzbuzz"
		}

		return "fizz"
	}

	if n%5 == 0 {
		return "buzz"
	}

	return fmt.Sprint(n)
}

Day 8

“I can’t go out, I have a test three weeks from now” student. Also friends with above couple, but a bit more reclusive. Really wants that A+. Strives to write code so perfectly commented that he ends up generating line noise. Diet consists of pizza, diet-coke, coffee and whatever energy drink is nearest.

Will have a meltdown if he ever leaves academia, especially if integrated into a “fast-paced, multitasking” environment with lots of legacy projects.

package day08

// import the "fmt" package, we'll need fmt.Sprint to convert integers to
// strings.
import "fmt"

// FizzBuzz takes a positive integer and returns a string. If the passed in
// integer is divisible by 3, the output is "fizz". If it is divisible by 5,
// the output is "buzz". If it is divisible by 3 and 5, the output is
// "FizzBuzz". Otherwise, the output is the number itself, converted to its
// decimal string representation.
func FizzBuzz(n int) string {

	// all numbers need to be tested for divisibility by both factors.
	// therefore, we optimize the program by performing these divisions only
	// once
	divisibleby3 := n%3 == 0
	divisibleby5 := n%5 == 0

	if divisibleby3 {
		// number is divisible by 3

		// each number must be tested for both factors
		if divisibleby5 {
			// number is divisible by 3 and 5.
			return "fizzbuzz"
		}

		// number is not divisible by 5, only by 3
		return "fizz"
	}

	// number is not divisible by 3 from this point on

	if divisibleby5 {
		// number is divisible by 5
		return "buzz"
	}

	// number does not have 3 or 5 as prime factors
	return fmt.Sprint(n)
}

Good luck kid. You’ll need a lot of it.