Some time ago I blogged about my first experience with F#. I took a course Functional Programming Principles in Scala recently and it somewhat opened my eyes on problem solving in functional style. After that I felt confident enough to do something more complex than fizzbuzz with F# so the logical next step was Bowling game kata.
Without further ado here are the tests:
let throwmany(amount, pins) = [ for n in 1..amount -> pins ]
[<TestFixture>] 
type BowlingGameTests()=   
    [<Test>]
    member x.``Bowling guttergame``() =
        let throws = throwmany(20, 0)
        score throws |> should equal 0
    [<Test>]
    member x.``Throw all ones``() =
        let throws = throwmany(20, 1) 
        score throws |> should equal 20
    [<Test>]
    member x.``Throw one spare``() =
        let sparethrows = [5; 5; 3]
        let manythrows=throwmany (17, 0)
        let throws = sparethrows @ manythrows
        score throws |> should equal 16
    [<Test>]
    member x.``Throw one strike``() =
        let throws = [10; 3; 4] @ throwmany (16, 0)
        score throws |> should equal 24
    [<Test>]
    member x.``Perfect game``() =
        let throws = throwmany (12, 10)
        score throws |> should equal 300
Tests are same as in the kata slides. Throwmany-function creates a list with as many items as given in amount-parameter and each item has the value given in pins-parameter.
Being the OOP-guy that I am I originally started thinking I need a Game-class that holds the state of the game. Each throw should be registered to Game using throw-method and so on. Then I tried to start thinking in a more functional way. If I give up maintaining state, I wouldn't need any throw-method. Then I wouldn't need any Game-class at all and I could do with just a score-function that takes list of throws. This is what I ended up with:
let private calculate_strike_score (throws: int list) = 
    if throws.Length>3 then 10+throws.Item(1)+throws.Item(2)
    else 10
let private calculate_spare_score (throws:int list) = 10+throws.Item(2)
let rec private score_throws (throws: int list) (score:int) =
    match throws with
    | [] -> score
    | throws when throws.Head = 10 
        -> score_throws throws.Tail score + calculate_strike_score(throws) 
    | throws when (throws.Head + throws.Tail.Head = 10) 
        -> score_throws throws.Tail.Tail score + calculate_spare_score(throws)
    | _ -> score_throws throws.Tail.Tail score + throws.Head+throws.Item(1)
let score throws = score_throws throws 0
Score-function calls recursive score_throws-function with initial score of 0. In score_throws the correct route is chosen with pattern matching. If the throws-list is empty, then everything has been done and the final score should be returned. If the first element is 10, then it's a strike. If two first elements combined is 10, then it's a spare. Otherwise it's a regular frame.
That's it. Tests are green. Time to move on to something more complex.
Software professional with a passion for quality. Likes TDD and working in agile teams. Has worked with wide-range of technologies, backend and frontend, from C++ to Javascript. Currently very interested in functional programming.
