Created
May 29, 2020 00:49
-
-
Save tecnowilliam/e3e0d662011cc1bc637d63dcb7dd5040 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| % Compile: | |
| % c(rpss). | |
| -module(rpss). | |
| -author("William Vargas"). | |
| -version("1.0"). | |
| -export([ | |
| play/1, | |
| echo/1, | |
| play_two/3, | |
| rock/1, | |
| no_repeat/1, | |
| enum/1, | |
| cycle/1, | |
| rand/1, | |
| val/1, | |
| tournament/2, | |
| least_frequent/1, | |
| most_frequent/1, | |
| rand_play/1, | |
| best_play/2 | |
| ]). | |
| -type move() :: rock | paper | scissors. | |
| % | |
| % play one strategy against another, for N moves. | |
| % | |
| -spec play_two(function(),function(),integer()) -> ok | error. | |
| play_two(StrategyL,StrategyR,N) -> | |
| play_two(StrategyL,StrategyR,[],[],N). | |
| % tail recursive loop for play_two/3 | |
| % 0 case computes the result of the tournament | |
| % FOR YOU TO DEFINE | |
| % REPLACE THE dummy DEFINITIONS | |
| -spec play_two(function(),function(),[move()],[move()],integer()) -> ok | error. | |
| play_two(_,_,PlaysL,PlaysR,0) -> | |
| io:format("PlayerLeft: ~p~n",[PlaysL]), | |
| io:format("PlayerRight: ~p~n",[PlaysR]), | |
| io:format("Winner: ~p~n",[lists:sum(lists:map(fun outcome/1,lists:zipwith(fun result/2, PlaysL, PlaysR)))]); | |
| play_two(StrategyL,StrategyR,PlaysL,PlaysR,N) -> | |
| play_two(StrategyL, StrategyR,[StrategyL(PlaysR) | PlaysL],[StrategyR(PlaysL) | PlaysR], N-1). | |
| % | |
| % interactively play against a strategy, provided as argument. | |
| % | |
| -spec play(function()) -> ok | error. | |
| play(Strategy) -> | |
| io:format("Rock - paper - scissors~n"), | |
| io:format("Play one of rock, paper, scissors, ...~n"), | |
| io:format("... r, p, s, stop, followed by '.'~n"), | |
| play(Strategy,[]). | |
| % tail recursive loop for play/1 | |
| -spec play(function(),[move()]) -> ok | error. | |
| play(Strategy,Moves) -> | |
| {ok,P} = io:read("Play: "), | |
| Play = expand(P), | |
| case Play of | |
| stop -> | |
| io:format("Stopped~n"); | |
| _ -> | |
| Move = Strategy(Moves), | |
| Result = result(Play,Move), | |
| % io:format("Play: ~p~n",[Play]), | |
| io:format("Move: ~p~n",[Move]), | |
| io:format("Result: ~p~n",[Result]), | |
| play(Strategy,[Play|Moves]) | |
| end. | |
| % | |
| % auxiliary functions | |
| % | |
| % transform shorthand atoms to expanded form | |
| -spec expand(atom()) -> atom(). | |
| expand(r) -> rock; | |
| expand(p) -> paper; | |
| expand(s) -> scissors; | |
| expand(X) -> X. | |
| % result of one set of plays | |
| -spec result(atom(),atom()) -> atom(). | |
| result(rock,rock) -> draw; | |
| result(rock,paper) -> lose; | |
| result(rock,scissors) -> win; | |
| result(paper,rock) -> win; | |
| result(paper,paper) -> draw; | |
| result(paper,scissors) -> lose; | |
| result(scissors,rock) -> lose; | |
| result(scissors,paper) -> win; | |
| result(scissors,scissors) -> draw. | |
| % result of a tournament | |
| -spec tournament([move()],[move()]) -> list(). | |
| tournament(PlaysL,PlaysR) -> | |
| lists:sum( | |
| lists:map(fun outcome/1, | |
| lists:zipwith(fun result/2,PlaysL,PlaysR))). | |
| -spec outcome(atom()) -> integer(). | |
| outcome(win) -> 1; | |
| outcome(lose) -> -1; | |
| outcome(draw) -> 0. | |
| % transform 0, 1, 2 to rock, paper, scissors and vice versa. | |
| -spec enum(integer()) -> move(). | |
| enum(0) -> | |
| rock; | |
| enum(1) -> | |
| paper; | |
| enum(2) -> | |
| scissors. | |
| -spec val(move()) -> integer(). | |
| val(rock) -> | |
| 0; | |
| val(paper) -> | |
| 1; | |
| val(scissors) -> | |
| 2. | |
| % give the play which the argument beats. | |
| -spec beats(move()) -> move(). | |
| beats(rock) -> | |
| scissors; | |
| beats(paper) -> | |
| rock; | |
| beats(scissors) -> | |
| paper. | |
| -spec defeat(move()) -> move(). | |
| defeat(Move) -> | |
| beats(beats(Move)). | |
| -spec count_moves([move()],tuple()) -> tuple(). | |
| count_moves([],Moves) -> | |
| Moves; | |
| count_moves([X|Xs],{R,P,S}) -> | |
| case X of | |
| rock -> count_moves(Xs,{R+1,P,S}); | |
| paper -> count_moves(Xs,{R,P+1,S}); | |
| _ -> count_moves(Xs,{R,P,S+1}) | |
| end. | |
| % | |
| % strategies. | |
| % | |
| -spec echo([move()]) -> move(). | |
| echo([]) -> | |
| paper; | |
| echo([Last|_]) -> | |
| Last. | |
| -spec rock(move()) -> rock. | |
| rock(_) -> | |
| rock. | |
| % FOR YOU TO DEFINE | |
| % REPLACE THE dummy DEFINITIONS | |
| -spec no_repeat([move()]) -> move(). | |
| no_repeat([]) -> | |
| paper; | |
| no_repeat([Move|_]) -> | |
| defeat(Move). | |
| -spec rand(move()) -> move(). | |
| rand(_) -> | |
| enum(rand:uniform(3) - 1). | |
| -spec cycle([move()]) -> move(). | |
| cycle(Xs) -> | |
| enum(length(Xs) rem 3). | |
| -spec least_frequent([move()]) -> move(). | |
| least_frequent(Xs) -> | |
| {R,P,S} = count_moves(Xs,{0,0,0}), | |
| case {R, P, S} of | |
| _ when R =< P andalso R =< S -> defeat(rock); | |
| _ when P =< R andalso P =< S -> defeat(paper); | |
| _ -> defeat(scissors) | |
| end. | |
| -spec most_frequent([move()]) -> move(). | |
| most_frequent(Xs) -> | |
| {R,P,S} = count_moves(Xs,{0,0,0}), | |
| case {R, P, S} of | |
| _ when R >= P andalso R >= S -> defeat(rock); | |
| _ when P >= R andalso P >= S -> defeat(paper); | |
| _ -> defeat(scissors) | |
| end. | |
| -spec rand_play([function()]) -> error_empty | move(). | |
| rand_play([]) -> | |
| error_empty; | |
| rand_play(Sx) -> | |
| play(lists:nth(rand:uniform(length(Sx)),Sx)). | |
| -spec best_play([function()],[move()]) -> error_empty | move(). | |
| best_play([],[]) -> | |
| error_empty; | |
| best_play([],_) -> | |
| []; | |
| best_play([S|Sx],P) -> | |
| [best_play(S,P,{0,0,0}),best_play(Sx,P)]. | |
| -spec best_play([function()],[move()],tuple()) -> list(). | |
| best_play(S,[],{W,D,L}) -> | |
| {S,{"Win",W},{"Draw",D},{"Lose",L}}; | |
| best_play(S,[P|Px],{W,D,L}) -> | |
| case result(P,S(Px)) of | |
| win -> best_play(S,Px,{W+1,D,L}); | |
| draw -> best_play(S,Px,{W,D+1,L}); | |
| _ -> best_play(S,Px,{W,D,L+1}) | |
| end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment