Just if anyones interested...
a friend tipped me off to another thing... (fun x y -> x + y) is the + operator..... obviously enough in retrospect.
Still not happy with the embedded if statement though.... I don't think its too clear.
my match basically is
if we are at the end of the game, dont score anymore frames
if we have an incomplete strike, score what we can
if strike, score strike and carry on
if normal frame, score it, if we got a spare then add on the extra and then carry on
otherwise, just add up whats there.
Thing is, without comments I can't see a way of introducing the language too easily. In C# / C++ you'd introudce an explaining variable / methods. Here I kind need a new kind of refactoring called "Introduce explaining pattern match" but I don't think I can do that. I'm not sure if it would help understanding if I could. It's still way more concise than any C# / Java / C++ I've seen for the same thing.
so...the code
#light
open System
open NUnit.Framework
let score_bowls bowls =
let rec score_bowls' frame l =
let nextframe = score_bowls' (frame+1)
match l with
| _ when frame = 11 -> 0
| [10;s] -> 10 + s + s
| 10 :: s :: n :: tail -> 10 + s + n + nextframe (s :: n :: tail )
| f :: s :: n :: tail -> f + s + (if((f+s)=10) then n else 0) + nextframe (n :: tail)
| _ -> List.fold_right (+) l 0
score_bowls' 1 bowls
[<TestFixture>]
type BowlingTestCases = class
new() = {}
[<Test>]
member x.SimpleScoring() = Assert.AreEqual(6, score_bowls [1;2;3] )
[<Test>]
member x.ScoreSpare() = Assert.AreEqual(12, score_bowls [2;8;1] )
[<Test>]
member x.ScoreStrike() = Assert.AreEqual(16, score_bowls [10;1;2] )
[<Test>]
member x.ScorePerfectGame() = Assert.AreEqual( 300, score_bowls [for i in 1..12 -> 10] )
[<Test>]
member x.SpareLastFrame() = Assert.AreEqual( 11, score_bowls ([for i in 1..18 -> 0] @ [2;8;1]) )
[<Test>]
member x.StrikeLastFrame() = Assert.AreEqual( 21, score_bowls ([for i in 1..18 -> 0] @ [10;10;1]) )
[<Test>]
member x.DoubleStrike() = Assert.AreEqual(33, score_bowls [10;10;1] )
[<Test>]
member x.ExampleGame() = Assert.AreEqual(133, score_bowls [1;4;4;5;6;4;5;5;10;0;1;7;3;6;4;10;2;8;6] )
end
Keith Nicholas
http://designingcode.blogspot.com