/// one liner tennis kata let play x y = Seq.map([y,x,"A ";x,y,"B "].get_Item>>fun(w,l,p)->p+match !w with|3->(if !l=3 then l:=2;"advantage"else"win!")|2 when !l=3->w:=3;"deuce"|p->incr w;["15";"30";"40"].[p]) /// A wins a point let POINT_A = 0 /// B wins a point let POINT_B = 1 /// helper function to make game points let cycle points = seq {while true do yield! points} // A wins every point let game1 = cycle [POINT_A] // A and B swap points identically let game2 = cycle [POINT_A; POINT_B] // A and B trade points but A wins more points than B let game3 = cycle [POINT_A; POINT_B; POINT_A] /// print out the game result let print = String.concat"!, ">>printfn"%s" game1 |> play (ref 0) (ref 0) |> Seq.take 10 |> print // result: A 15!, A 30!, A 40!, A win! game2 |> play (ref 0) (ref 0) |> Seq.take 10 |> print // result: A 15!, B 15!, A 30!, B 30!, A 40!, B deuce!, A advantage!, B deuce!, A advantage!, B deuce! game3 |> play (ref 0) (ref 0) |> Seq.take 10 |> print // result: A 15!, B 15!, A 30!, A 40!, B 30!, A win! // simulate 1000 games and show how many times player A and player B wins. let randomGame = let rnd = new System.Random() seq { while true do yield if rnd.NextDouble() < 0.5 then POINT_A else POINT_B } seq { for i in 1 .. 1000 do yield randomGame |> play(ref 0)(ref 0) |> Seq.find(Seq.forall((<>)'!')>>not) } |> Seq.groupBy(Seq.forall((<>)'A')) |> Seq.iter(fun (k,v) -> printfn "%s wins %d times." (if k then "A" else "B") (Seq.length v)) // result: // A wins 498 times. // B wins 502 times.