10 people like it.

# Tennis Kata

Another solution to the Tennis Kata, to score a tennis game.

 ``` 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: ``` `````` /// The two players type Player = A | B /// The point score in for a player in a game type PlayerPoints = Zero | Fifteen | Thirty | Forty /// The score of a game type Score = | Points of PlayerPoints * PlayerPoints | Advantage of Player | Deuce | Game of Player /// Compute the next score in a game let nextPointScore a = match a with | Zero -> Fifteen | Fifteen -> Thirty | Thirty -> Forty | Forty -> failwith "what??" /// Check if we've reached deuce let normalize score = match score with | Points(Forty,Forty) -> Deuce | _ -> score /// Score a point in a game let scorePoint score point = match score, point with | Advantage player1, player2 when player1 = player2 -> Game player1 | Advantage player1, player2 -> Deuce | Deuce, player -> Advantage player | Points(Forty, _), A -> Game A | Points(_, Forty), B -> Game B | Points(a, b), A -> normalize (Points (nextPointScore a, b)) | Points(a, b), B -> normalize (Points (a, nextPointScore b)) | Game _ , _ -> (* printfn "the game is over!"; *) score /// Score a whole game, where the game is represented as a sequence of points let scoreGame (points: seq) = Seq.scan scorePoint (Points(Zero,Zero)) points /// A sample game - A wins every point let game1 = seq { while true do yield A } /// A sample game - A and B swap points indefinitely let game2 = seq { while true do yield A yield B } /// A sample game - A and B trade points but A wins more points than B let game3 = seq { while true do yield A yield B yield A } scoreGame game1 |> Seq.truncate 10 |> Seq.toList scoreGame game2 |> Seq.truncate 10 |> Seq.toList scoreGame game3 |> Seq.truncate 10 |> Seq.toList /// Generate a random game let randomGame i = let rnd = new System.Random(i) seq { while true do if rnd.NextDouble() < 0.5 then yield A else yield B } // Random testing of 1000 games for i in 1 .. 1000 do scoreGame (randomGame i) |> Seq.nth 10 |> printfn "result is %A" ``````
union case Player.A: Player
union case Player.B: Player
type PlayerPoints =
| Zero
| Fifteen
| Thirty
| Forty

Full name: Script.PlayerPoints

The point score in for a player in a game
union case PlayerPoints.Zero: PlayerPoints
union case PlayerPoints.Fifteen: PlayerPoints
union case PlayerPoints.Thirty: PlayerPoints
union case PlayerPoints.Forty: PlayerPoints
type Score =
| Points of PlayerPoints * PlayerPoints
| Advantage of Player
| Deuce
| Game of Player

Full name: Script.Score

The score of a game
union case Score.Points: PlayerPoints * PlayerPoints -> Score
union case Score.Advantage: Player -> Score
type Player =
| A
| B

Full name: Script.Player

The two players
union case Score.Deuce: Score
union case Score.Game: Player -> Score
val nextPointScore : a:PlayerPoints -> PlayerPoints

Full name: Script.nextPointScore

Compute the next score in a game
val a : PlayerPoints
val failwith : message:string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith
val normalize : score:Score -> Score

Full name: Script.normalize

Check if we've reached deuce
val score : Score
val scorePoint : score:Score -> point:Player -> Score

Full name: Script.scorePoint

Score a point in a game
val point : Player
val player1 : Player
val player2 : Player
val player : Player
val b : PlayerPoints
val scoreGame : points:seq<Player> -> seq<Score>

Full name: Script.scoreGame

Score a whole game, where the game is represented as a sequence of points
val points : seq<Player>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
module Seq

from Microsoft.FSharp.Collections
val scan : folder:('State -> 'T -> 'State) -> state:'State -> source:seq<'T> -> seq<'State>

Full name: Microsoft.FSharp.Collections.Seq.scan
val game1 : seq<Player>

Full name: Script.game1

A sample game - A wins every point
val game2 : seq<Player>

Full name: Script.game2

A sample game - A and B swap points indefinitely
val game3 : seq<Player>

Full name: Script.game3

A sample game - A and B trade points but A wins more points than B
val truncate : count:int -> source:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.truncate
val toList : source:seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.Seq.toList
val randomGame : i:int -> seq<Player>

Full name: Script.randomGame

Generate a random game
val i : int
val rnd : System.Random
namespace System
Multiple items
type Random =
new : unit -> Random + 1 overload
member Next : unit -> int + 2 overloads
member NextBytes : buffer:byte[] -> unit
member NextDouble : unit -> float

Full name: System.Random

--------------------
System.Random() : unit
System.Random(Seed: int) : unit
System.Random.NextDouble() : float
val i : int32
val nth : index:int -> source:seq<'T> -> 'T

Full name: Microsoft.FSharp.Collections.Seq.nth
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn