Phillip Trelford's Array

POKE 36879,255

Functional Fizz Buzz

Fizz-Buzz or Bizz Buzz is a word game, popularized by Jeff Atwood in the article:

Why Can’t Programmers… Program?

The game has been turned into a simple programming test:

Write a program that prints the numbers from 1 to 100. But for multiples of 3 print "Fizz" instead of the number and for the multiples of 5 print "Buzz". For numbers which are multiples of both 3 and 5 print "FizzBuzz".

If you’re involved in hiring programmers then the article is probably worth a read.

This kind of problem can be expressed very concisely in functional programming languages to the point where the code fits in a tweet.

Haskell

Last month Calvin Bottoms posted an article describing and implementation of Fizz-Buzz in Haskell expressed in a mere 78 characters:

[max(show x)(concat[n|(f,n)<-[(3,"Fizz"),(5,"Buzz")],mod x f==0])|x<-[1..100]]

Higher order functions and list comprehensions (a feature taken from Miranda) make this very terse, but also a little impenetrable.

F#

Rather more verbose (122 characters) but perhaps a little more readable:

for n in 1..100 do printfn "%s" <| match n%3, n%5 with 
0,0 -> "FizzBuzz" | 0,_ -> "Fizz" | _,0 -> "Buzz" | _,_ -> string n

Pattern matching makes the various states relatively obvious.

Clojure

Martin Trojer sent over this quite elegant Clojure implementation via Twitter:

(map #(cond (zero? (mod % 15)) "FizzBuzz" (zero? (mod % 3)) "Fizz" 
(zero? (mod % 5)) "Buzz" :else %) (range 1 101))

Testing for “FizzBuzz” using modulus 15 helps reduce the character count.

Erlang

I’ve been playing with Erlang recently and Fizz-Buzz is my new “Hello World” app. This was my first effort:

f(101)->ok;
f(X)->Y=case{X rem 3,X rem 5}of{0,0}->fizzbuzz;{0,_}->fizz;{_,0}->buzz;
{_,_}->X end,io:format("~w~n",[Y]),f(X+1). 

Erlang doesn’t have a for loop construct built-in so I resorted to recursion instead.

That said you can achieve the same thing using the lists module seq and foreach functions:

lists:foreach(fun(X)->io:format("~w~n",[case{X rem 3,X rem 5}of{0,0}->fizzbuzz;
{0,_}->fizz;{_,0}->buzz;{_,_}->X end])end,lists:seq(1,100)).

Next?

Is Fizz-Buzz the new “Hello World”?

I think it might be, despite Jeff’s protestations, take a peek at Fizz-Buzz on Rosetta Code.

Functional Programming eXchange 2012

Less than a month to go now until the first FP event of this year – the Functional Programming eXchange at Skills Matter in London on March 16th.

functionalpx-670x180

Robert Pickering has put together another great line up including on the F# side Tomas Petricek on F# 3.0’s Type Providers and Loic Denuziere on F# in large scale web apps. There’s also a good number of talks from members of the Clojure, Scala and Haskell communities.

Rob lists plenty of reasons to come to Functional Programming eXchange 2012, on his blog. The case studies on FP in real world applications look particularly compelling and Scala’s AKKA framework is definitely worth a look. Not forgetting the socializing and inevitable pub outing afterwards…

FP Day Cambridge 2011

FP Day saw talks from luminaries in the Functional Programming world, Simon Peyton-Jones and Don Syme give key notes, with hands-on tutorials and experience reports on F#, Clojure and Haskell sandwiched in the middle. Tomas Petricek and I provided the F# filling, and Zach Bray applied the F# source.

FPDayLogo453x132

Turning to the Functional Side With F#

F# is a multi-paradigm programming language with first-class support for Functional Programming, and ships with Visual Studio 2010. Using a mixture of presentation and practical exercises this session aims to help you:

  • learn how to use F#
  • think in a functional way
  • model problem domains using functional types

Tasks Download: http://tomasp.net/fpday.zip & Code Samples on Github

The morning tasks were based on a Point-of-sale (POS) application.

Domain Model:

namespace Checkout

// Common types

type Code = string
type Name = string
type Price = decimal
type Product = Product of Code * Name * Price
type Quantity = decimal

/// Tender types
type Tender =
  | Cash
  | Card of string
  | Voucher

/// Represents line item
type LineItem = 
  | SaleLineItem of int * Product * Quantity
  | TenderLineItem of Tender * Price
  | CancelLineItem of int

Product lookup:

[<AutoOpen>]
module Products = 
    let products = [
            Product("8717644012208","Lynx Africa",2.49M)
            Product("5010123730215","Listerine",2.49M)
            Product("5000347009242","Aquafresh",1.99M)
            Product("5045094763863","Ibuprofen", 1.99M)]
    let Lookup code = 
        products |> Seq.tryFind (function Product(code',_,_) -> code' = code)

Functions to be implemented in the task:

[<AutoOpen>]
module Lines =
    let saleTotal lines =
        lines |> List.sumBy (fun line ->
            match line with
            | SaleLineItem(id,Product(_,_,price),quantity) -> price*quantity
            | _ -> 0.0M
        )
    let tenderTotal lines =
        raise (new System.NotImplementedException())
    let cancelTotal lines =
        raise (new System.NotImplementedException())

Sale type:

type Sale () =
    let mutable items = []    
    member sale.AddItem (item:LineItem) = items <- item::items
    member sale.TotalAmount = saleTotal items - cancelTotal items
    member sale.OutstandingAmount = sale.TotalAmount - tenderTotal items
    member sale.ChangeDue = 
        if sale.OutstandingAmount < 0M 
        then -sale.OutstandingAmount
        else 0M

Failing tests:

open NUnit.Framework

[<TestFixture>]
module Tests = 
  open System.Diagnostics

  [<Test>]
  let ``Over tendering with cash should give change`` () =
    let sale = Sale()
    let product = Product("123", "3 Pay As you Go", 10.0M)
    sale.AddItem(SaleLineItem(1, product, 1.0M))
    sale.AddItem(TenderLineItem(Cash,20.00M))
    Assert.That(sale.ChangeDue = 10.0M)

  [<Test>]
  let ``Tendering full amount with card should leave no change`` () =
    let sale = Sale()
    let product = Product("123", "3 Pay As you Go", 10.0M)
    sale.AddItem(SaleLineItem(1, product, 1.0M))
    sale.AddItem(TenderLineItem(Card("1234123412341234"), 10.00M))
    Assert.That(sale.ChangeDue = 0.0M)

  [<Test>]
  let ``Cancelled items should not be charged`` () = 
    let sale = Sale()
    let product = Product("123", "3 Pay As you Go", 10.0M)
    sale.AddItem(SaleLineItem(1, product, 1.0M))
    sale.AddItem(CancelLineItem(1))
    Assert.That(sale.OutstandingAmount = 0.0M)

  do
    ``Over tendering with cash should give change`` ()
    ``Tendering full amount with card should leave no change`` ()
    ``Cancelled items should not be charged`` ()

If you'd like to learn more about F#, there are still places left at the Progressive F# Tutorials at Skills Matter in London on November 3-4th:

progfsharp_tutorials