Sunday, March 10, 2013

F# FizzBuzz using Functions

"Success is neither magical nor mysterious. Success is the natural consequence of consistently applying the basic fundamentals."
-- Jim Rohn

"When I was young, I had to learn the fundamentals of basketball. You can have all the physical ability in the world, but you still have to know the fundamentals."
-- Michael Jordan

FizzBuzz is one of the most basic programs that is doable in an interview, yet hard enough that it can be used to filter out candidates.  The problem you need to solve is simple.

Print out all of the numbers from 1 to 100.  If a number is divisible by 3 then print out Fizz.  If a number is divisible by 5 then print out Buzz.  If a number is divisible by both 3 and 5 then print out FizzBuzz.



A simple problem which make for a good kata, but deep enough that there are a lot of different ways to solve the problem.  I've been doing an F# kata-a-day for about 6 months now and recently I decided to do FizzBuzz again but to try not to test for 15 directly.  I thought about it a little bit and it hit me.  What I want to do is map a number divisible by 3 to Fizz, number divisible by 5 to Buzz, and if it is divisible by both then map it to both.

I create two function to support my mapping.


let fizzer n =
  if n % 3 = 0 then "Fizz"
  else ""

let buzzer n =
  if n % 5 = 0 then "Buzz"
  else ""


Since I do TDD, I used the following FsUnit test to drive out these two function.


[<Test>]
let ``Validate that 18 is Fizz`` () =
  fizzer 18 |> should equal "Fizz"

[<Test>]
let ``Validate that 4 is not Fizz`` () =
  fizzer 4 |> should equal ""

[<Test>]
let ``Validate that 20 is Buzz`` () =
  buzzer 20 |> should equal "Buzz"

[<Test>]
let ``Validate that 22 is not Buzz`` () =
  buzzer 22 |> should equal ""


Now what I need is a function which will map these two functions.


let fizzBuzzer num =
  let result = [fizzer; buzzer] |> List.map (fun x -> x num) |> List.reduce (fun acc x -> acc + x)
  if result = "" then num.ToString()
  else result


What fizzBuzzer does is map the number given to it against the functions fizzer and buzzer created above.  This gives two results which are then folded using List.reduce.  This gives use four different cases:

  1. "" (empty string)
  2. "Fizz"
  3. "Buzz"
  4. "FizzBuzz"

In the case of the empty string what we want to do is return the number given to fizzBuzzer as a string (e.g. fizzBuzzer(2) returns "2").  In order to do that we look at the result from the step above, if it is the first case then we return the number passed in as a string using toString.

There you have it.  FizzBuzz without a direct check for 15!  And it uses higher order functions!

Full code from my 25 min kata is below.  It can also be found on Try F#.

open NUnit.Framework
open FsUnit

let fizzer n =
  if n % 3 = 0 then "Fizz"
  else ""

let buzzer n =
  if n % 5 = 0 then "Buzz"
  else ""

let fizzBuzzer num =
  let result = [fizzer; buzzer] |> List.map (fun x -> x num) |> List.reduce (fun acc x -> acc + x)
  if result = "" then num.ToString()
  else result

[<Test>]
let ``Validate that 3 is Fizz`` () =
  fizzBuzzer 3 |> should equal "Fizz"

[<Test>]
let ``Validate that 9 is Fizz`` () =
  fizzBuzzer 9 |> should equal "Fizz"

[<Test>]
let ``Validate that 5 is Buzz`` () =
  fizzBuzzer 5 |> should equal "Buzz"

[<Test>]
let ``Validate that 25 is Buzz`` () =
  fizzBuzzer 25 |> should equal "Buzz"

[<Test>]
let ``Validate that 2 is 2`` () =
  fizzBuzzer 2 |> should equal "2"

[<Test>]
let ``Validate that 15 is FizzBuzz`` () =
  fizzBuzzer 15 |> should equal "FizzBuzz"

[<Test>]
let ``Validate that 30 is FizzBuzz`` () =
  fizzBuzzer 30 |> should equal "FizzBuzz"

[<Test>]
let ``Validate that 18 is Fizz`` () =
  fizzer 18 |> should equal "Fizz"

[<Test>]
let ``Validate that 4 is not Fizz`` () =
  fizzer 4 |> should equal ""

[<Test>]
let ``Validate that 20 is Buzz`` () =
  buzzer 20 |> should equal "Buzz"

[<Test>]
let ``Validate that 22 is not Buzz`` () =
  buzzer 22 |> should equal ""