Skip to content

Instantly share code, notes, and snippets.

@pbouzakis
Last active November 22, 2017 18:28
Show Gist options
  • Save pbouzakis/88bb76316f6fb8295db5d175b148b975 to your computer and use it in GitHub Desktop.
Save pbouzakis/88bb76316f6fb8295db5d175b148b975 to your computer and use it in GitHub Desktop.
OCaml Tennis Kata
(* Tennis Kata in OCaml! *)
type player = PlayerOne | PlayerTwo
type point = Love | Fifteen | Thirty
type score =
| Points of point * point
| Forty of player * point
| Duece
| Advantage of player
| GameOver of player
let is_player_one p =
p = PlayerOne
let new_game =
Points(Love, Love)
let transition_to_forty score player =
match score with
| Points (p1_point, p2_point) ->
if is_player_one player then Forty(PlayerOne, p2_point)
else Forty(PlayerTwo, p1_point)
| _ -> score (* You can only goto Forty from Points *)
let transition_to_duece score player =
match score with
| Forty (player_w_forty, other_point) ->
if player_w_forty <> player then Duece else score
| Advantage (player_w_adv) ->
Duece
| _ -> score (* You can only goto Duece from Forty *)
let transition_to_advantage score player =
match score with
| Duece -> Advantage(player)
| _ -> score (* You can only goto Advantage from Deuce *)
let transition_to_gameover score player =
match score with
| Advantage (player_w_adv) ->
if player_w_adv = player then GameOver(player) else score
| Forty (player_w_forty, other_point) ->
if player_w_forty = player then GameOver(player) else score
| _ -> score (* You can only goto GameOver from Advantage & Forty *)
let next_score_from_points point other_point player score =
match point with
| Love -> Points(Fifteen, other_point)
| Fifteen -> Points(Thirty, other_point)
| Thirty -> transition_to_forty score player
let next_score_from_forty player_w_forty point score player =
match point with
| Love -> Forty(player_w_forty, Fifteen)
| Fifteen -> Forty(player_w_forty, Thirty)
| Thirty -> transition_to_duece score player
let player_scored score player =
match score with
| Points (p1, p2) ->
if is_player_one player then next_score_from_points p1 p2 player score
else next_score_from_points p2 p1 player score
| Forty (player_w_forty, other_point) ->
if player_w_forty = player then transition_to_gameover score player
else next_score_from_forty player_w_forty other_point score player
| Duece -> transition_to_advantage score player
| Advantage (player_w_adv) ->
if player_w_adv = player then transition_to_gameover score player
else transition_to_duece score player
| GameOver (winner) -> GameOver (winner) (* Still the winner *)
(* Output as string helpers *)
let player_to_str = function
| PlayerOne -> "Player 1"
| PlayerTwo -> "Player 2"
let point_to_str = function
| Love -> "love"
| Fifteen -> "15"
| Thirty -> "30"
let score_line p1 p2 =
"Player 1: " ^ p1 ^ " Player 2: " ^ p2
let score_to_str = function
| Points (p_one, p_two) ->
score_line (point_to_str p_one) (point_to_str p_two)
| Forty (player_w_forty, other) ->
if is_player_one player_w_forty then score_line "40" (point_to_str other)
else score_line (point_to_str other) "40"
| Duece ->
"At duece"
| Advantage (player) ->
"Advantage " ^ player_to_str player
| GameOver (player) ->
"Game over! " ^ player_to_str player ^ " has won."
(* "Test" scenarios *)
let scenario_one_player1_kills start_game =
let score_1 = player_scored new_game PlayerOne in
let score_2 = player_scored score_1 PlayerOne in
let score_3 = player_scored score_2 PlayerOne in
let score_4 = player_scored score_3 PlayerOne in
"START\n" ^
(score_to_str start_game) ^ "\n" ^
(score_to_str score_1) ^ "\n" ^
(score_to_str score_2) ^ "\n" ^
(score_to_str score_3) ^ "\n" ^
(score_to_str score_4) ^ "\n" ^
"END"
let scenario_two_good_game start_game =
let score_1 = player_scored new_game PlayerOne in
let score_2 = player_scored score_1 PlayerOne in
let score_3 = player_scored score_2 PlayerOne in
let score_4 = player_scored score_3 PlayerTwo in
let score_5 = player_scored score_4 PlayerTwo in
let score_6 = player_scored score_5 PlayerTwo in
let score_7 = player_scored score_6 PlayerTwo in
let score_8 = player_scored score_7 PlayerOne in
let score_9 = player_scored score_8 PlayerOne in
let score_10 = player_scored score_9 PlayerOne in
"START (scenario_two_good_game)\n" ^
(score_to_str start_game) ^ "\n" ^
(score_to_str score_1) ^ "\n" ^
(score_to_str score_2) ^ "\n" ^
(score_to_str score_3) ^ "\n" ^
(score_to_str score_4) ^ "\n" ^
(score_to_str score_5) ^ "\n" ^
(score_to_str score_6) ^ "\n" ^
(score_to_str score_7) ^ "\n" ^
(score_to_str score_8) ^ "\n" ^
(score_to_str score_9) ^ "\n" ^
(score_to_str score_10) ^ "\n" ^
"END"
let () =
print_endline (scenario_one_player1_kills new_game)
let () =
print_endline (scenario_two_good_game new_game)
(*
DEBUGGIN'
print_endline (score_to_str (Points(Love, Love)));;
print_endline (score_to_str (Points(Love, Fifteen)));;
print_endline (score_to_str (Forty(PlayerOne, Fifteen)));;
print_endline (score_to_str (Forty(PlayerTwo, Thirty)));;
print_endline (score_to_str (Advantage(PlayerTwo)));;
print_endline (score_to_str (Advantage(PlayerOne)));;
print_endline (score_to_str (GameOver(PlayerOne)));;
print_endline (score_to_str (transition_to_forty (Points(Love, Fifteen)) PlayerOne));;
print_endline (score_to_str (transition_to_forty (Points(Love, Fifteen)) PlayerTwo));;
print_endline (score_to_str (transition_to_duece (Forty(PlayerOne, Fifteen))));;
print_endline (score_to_str (transition_to_advantage (Duece) PlayerOne));;
print_endline (score_to_str (transition_to_advantage (Duece) PlayerTwo));;
print_endline (score_to_str (transition_to_gameover (Advantage(PlayerTwo)) PlayerTwo));;
print_endline (score_to_str (transition_to_gameover (Advantage(PlayerOne)) PlayerTwo));;
print_endline (score_to_str (transition_to_gameover (Forty(PlayerTwo, Love)) PlayerTwo));;
print_endline (score_to_str (transition_to_gameover (Forty(PlayerOne, Fifteen)) PlayerTwo));;
*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment