Skip to content

Instantly share code, notes, and snippets.

@pazworld
Last active October 10, 2020 14:43
Show Gist options
  • Save pazworld/c5f189549815a4b6a90312c2db4e4684 to your computer and use it in GitHub Desktop.
Save pazworld/c5f189549815a4b6a90312c2db4e4684 to your computer and use it in GitHub Desktop.
BowlingGameKata in Erlang 3
-module(bowling_game).
-export([new/0, game/1]).
new() ->
spawn(?MODULE, game, [[]]).
game(Rolls) ->
receive
{roll, Pins} -> game([Pins | Rolls]);
{score, Sender} -> Sender ! score(lists:reverse(Rolls))
end.
% All rolls are processed
score([]) ->
0;
% 10th frame
score([Pins1, Pins2, Pins3]) ->
Pins1 + Pins2 + Pins3;
% Strike
score([10, Pins2, Pins3 | Rolls]) ->
10 + Pins2 + Pins3 + score([Pins2, Pins3 | Rolls]);
% Spare
score([Pins1, Pins2, Pins3 | Rolls]) when Pins1 + Pins2 =:= 10 ->
10 + Pins3 + score([Pins3 | Rolls]);
% Not strike nor spare
score([Pins1, Pins2 | Rolls]) ->
Pins1 + Pins2 + score(Rolls).
-module(bowling_game_test).
-include_lib("eunit/include/eunit.hrl").
gutter_game_test() ->
G = bowling_game:new(),
roll_many(G, 20, 0),
?assertEqual(0, score(G)),
ok.
all_ones_test() ->
G = bowling_game:new(),
roll_many(G, 20, 1),
?assertEqual(20, score(G)),
ok.
one_spare_test() ->
G = bowling_game:new(),
G ! {roll, 5},
G ! {roll, 5},
G ! {roll, 3},
roll_many(G, 17, 0),
?assertEqual(16, score(G)),
ok.
one_strike_test() ->
G = bowling_game:new(),
G ! {roll, 10},
G ! {roll, 3},
G ! {roll, 4},
roll_many(G, 16, 0),
?assertEqual(24, score(G)),
ok.
perfect_game_test() ->
G = bowling_game:new(),
roll_many(G, 12, 10),
?assertEqual(300, score(G)),
ok.
roll_many(G, N, Pins) ->
[G ! {roll, Pins} || _ <- lists:seq(1, N)].
score(G) ->
G ! {score, self()},
receive
Score -> Score
after 10 ->
throw(timeout)
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment