FizzBuzz summary

Created 20th July, 2008 05:52 (UTC), last edited 20th July, 2008 06:00 (UTC)

On Wednesday evening the BeerCampers did discuss the FizzBuzz problem when not distracted by such things as:

  • The difference between wheat beer and lager,
  • Baby blankets,
  • Why some Linux laptops have the Windows logo on the keyboard,
  • Working out scherrey's matchstick system for paying for beers,
  • Trying to get the wifi working so we could actually look at the FizzBuzz solutions on here.

Both Mike and scherrey came up with fully parametrised versions, one in Python, the other in JavaScript:

fizzbuzz_style_game = function (rules) {
    return function (n) {
       var result = "";
       for (var divisor in rules) 
            result += n%divisor?"":rules[divisor];
       return result || n}
}
# And even shorter than the initial fixed version!
def flex_fizzbuzz( start = 1, end = 101, mark = { 3:'Fizz', 5:'Buzz' } ):
    for n in range( start, end ):
        result = ""
        for val in mark:
            if not n % val: result += mark[ val ]
        print result or n

The interesting thing with both of these is that they are at least as clear as the naïve versions, but are now much more configurable.

Neither of them however allow the order of the rules to be controlled. I wonder how stable the Python ordering is due to the non-sorting of the keys in a dict.

scherrey's version does print the results (Mike's returns the value for any number), but as a consequence of course Mike's is testable in a way that scherrey's isn't. Although we could capture stdout and check that, it's much simpler to include the checks in the software itself using a more traditional unit testing library.

I would love to see what Somchok could do to write a C# version that is equally configurable. I suspect that this is somewhere that weakly typed languages really win over strongly typed ones.

for (int i = 1; i <= 100; i++) { Console.WriteLine((i % 3 == 0 && i % 5 == 0) ? "FizzBuzz" : ((i % 3 == 0) ? "Fizz" : (i % 5 == 0) ? "Buzz" : i.ToString())); }

John Berns solution is certainly imaginative and very definitely tongue in cheek, but does also raise a serious matter. Sometimes the right solution is not technological. We shouldn't be afraid to proffer non-software solutions when they're the most appropriate.

pphetra's lazy Haskell version is nice – lazy Haskell is always kind of cool. The rules are somewhat configurable as the divisor can be changed by altering the length of the two lists, but you can't change the number of lists (and hence the number of rules) quite so easily.

fizz = concat $ repeat [ "", "", "fizz" ]
buzz = concat $ repeat [ "", "", "", "", "buzz" ]
nums = map show [ 1.. ]
fizzbuzz = zipWith (\n fb -> if fb == "" then n else fb) nums (zipWith (++) fizz buzz)

When I tried some other Haskell versions I wanted to see if it was possible to make use of the Haskell equivalent of null or Nothing and come up with what is certainly a very ugly solution:

fizzbuzz = map ( number. buzz . fizz ) [ 1..100 ]
    where
        fizz n =
            if n `mod` 3 > 0 then (n, Nothing)
            else (n, Just "Fizz")
        buzz (n, v) =
            if n `mod` 5 > 0 then (n, v)
            else case (n, v) of
                (n, Nothing) -> (n, Just "Buzz")
                (n, Just t) -> (n, Just (t ++ "Buzz"))
        number x = case x of
            (n, Nothing) -> show n
            (n, Just t) -> t

That certainly isn't going to win any prizes for elegance, configurability or anything else other than maybe a special prize for most stupid application of the Maybe monad.

I have quite a few ideas for the next puzzle and about a week to decide which to use. Stay tuned.