Skip to content

Instantly share code, notes, and snippets.

@7-fl
Last active March 22, 2017 17:06
Show Gist options
  • Select an option

  • Save 7-fl/82d0324f83c9cc9b412bc7e970104de0 to your computer and use it in GitHub Desktop.

Select an option

Save 7-fl/82d0324f83c9cc9b412bc7e970104de0 to your computer and use it in GitHub Desktop.
Finished! + After the fact, I was able to implement more comprehensive testing.
-module(rps).
-compile(export_all).
-include_lib("eunit/include/eunit.hrl").
%
% play one strategy against another, for N moves.
%
play_two(S1, S2, N) ->
play_two(S1, S2, N, [], [], 0). %Added 0 variable to sum the score.
% tail recursive loop for play_two/3
% 0 case computes the result of the tournament
% FOR YOU TO DEFINE
% REPLACE THE dummy DEFINITIONS
play_two(_, _, 0, _, _, Score) ->
print_tournament_winner(Score);
play_two(S1, S2, N, Ls, Rs, Score) ->
PlayL = S1(Rs),
PlayR = S2(Ls),
Result = result(PlayL, PlayR),
print_round_winner(Result),
play_two(S1, S2, N-1, [PlayL|Ls], [PlayR|Rs], Score+outcome(Result) ).
print_round_winner(Result) ->
Results = case Result of
win -> [won, lost];
draw -> [draw, draw];
lose -> [lost, won]
end,
io:format("StrategyL: ~5w, StrategyR: ~5w~n", Results).
print_tournament_winner(Score) ->
Winner = if
Score>0 -> "StrategyL";
Score<0 -> "StrategyR";
Score=:=0 -> "--Draw--"
end,
io:format("Tournament Winner:~n\t~s (Score: ~w)~n", [Winner, abs(Score)]).
%
% interactively play against a strategy, provided as argument.
%
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,[], 0).
% tail recursive loop for play/1
play(Strategy, Moves, Score) ->
{ok,P} = io:read("Play: "),
Play = expand(P),
case Play of
stop ->
Winner = if
Score>0 -> "You!";
Score<0 -> "The Strategy";
Score=:=0 -> "--Draw--"
end,
io:format("Tournament winner: ~s (Score: ~w)~n", [Winner, abs(Score)]),
io:format("Stopped~n");
_ ->
Result = result(Play,Strategy(Moves)),
io:format("Result: ~p~n",[Result]),
play(Strategy,[Play|Moves], Score+outcome(Result))
end.
%
% auxiliary functions
%
% transform shorthand atoms to expanded form
expand(r) -> rock;
expand(p) -> paper;
expand(s) -> scissors;
expand(X) -> X.
% result of one set of plays
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
tournament(PlaysL,PlaysR) ->
lists:sum(
lists:map(fun outcome/1,
lists:zipwith(fun result/2,PlaysL,PlaysR))).
outcome(win) -> 1;
outcome(lose) -> -1;
outcome(draw) -> 0.
% transform 0, 1, 2 to rock, paper, scissors and vice versa.
enum(0) ->
rock;
enum(1) ->
paper;
enum(2) ->
scissors.
val(rock) ->
0;
val(paper) ->
1;
val(scissors) ->
2.
% give the play which the argument beats.
beats(rock) ->
paper;
beats(paper) ->
scissors;
beats(scissors) ->
rock.
%
% strategies.
%
echo([]) ->
paper;
echo([Last|_]) ->
Last.
rock(_) ->
rock.
% FOR YOU TO DEFINE
% REPLACE THE dummy DEFINITIONS
%---------
plays() ->
[rock, paper, scissors].
%---------
no_repeat_test() ->
%Test empty list of Opponent's plays:
OppPlays1 = [],
Responses1 = plays(),
loop(10, Responses1, fun rps:no_repeat/2, OppPlays1),
%Test non-empty list of Oppenents Plays:
OppPlays2 = [rock], %Opp => Opponent
Responses2 = others( my_hd(OppPlays2) ),
loop(10, Responses2, fun rps:no_repeat/2, OppPlays2),
OppPlays3 = [paper, scissors, paper],
Responses3 = others( my_hd(OppPlays3) ),
loop(10, Responses3, fun rps:no_repeat/2, OppPlays3),
all_tests_passed.
%Replaced the following to make testing easier:
%no_repeat([]) -> %First play, no list of opponent's plays.
% rand([]);
%no_repeat([Play|_]) ->
% Others = others(Play),
% rand_from(Others, fun random:uniform/1).
no_repeat(OppPlays) ->
no_repeat(OppPlays, fun random:uniform/1). %Allows me to write tests for no_repeat/2,
%by passing in a determinstic RandFunc of my
no_repeat([], RandFunc) -> %own, e.g. fun(_Len) -> 1 end, in place of
rand_from(plays(), RandFunc); %random:uniform/1
no_repeat([Play|_], RandFunc) ->
Others = others(Play),
rand_from(Others, RandFunc).
%---------
%loop_test() ->
%loop(0, a, b, c),
%loop(3, [rock, paper], fun rps:const/2, [rock, paper, paper, scissors]),
%all_tests_passed.
loop(0, _, _, _) ->
ok;
loop(N, Responses, Strategy, OppPlays) when N >=0 ->
RandNum = random:uniform( len(Responses) ), %Get random index value in Responses list.
TestRandFunc = fun(_X) -> RandNum end, %Create a determinstic RandFunc.
Expected = get_elmt(RandNum, Responses), % Expected Play corresponding to RandFunc.
Expected = Strategy(OppPlays, TestRandFunc), %See if the Strategy returns Expected.
loop(N-1, Responses, Strategy, OppPlays).
%---------
others_test() ->
[scissors, paper] = others(rock),
[scissors, rock] = others(paper),
[paper, rock] = others(scissors),
all_tests_passed.
others(Play) ->
others(Play, plays(), []).
others(_Play, [], Others) ->
Others;
others(Play, [Play|Ps], Others)->
others(Play, Ps, Others);
others(Play, [P|Ps], Others) ->
others(Play, Ps, [P|Others]).
%-------------
%rand_from() is a helper function that returns a random element from a list.
rand_from_test() ->
RandFunc1 = fun(_X) -> 1 end,
RandFunc2 = fun(_X) -> 2 end,
L = [a, b, c],
a = rand_from(L, RandFunc1),
b = rand_from(L, RandFunc2),
all_tests_passed.
rand_from(L) when length(L)>0 ->
rand_from(L, fun random:uniform/1). %This allows me to write tests for rand_from/2
%by passing in a determinstic RandFunc of my
rand_from(L, RandFunc) -> %own, e.g. fun(_Len) -> 1 end, in place of
RandNum = RandFunc( len(L) ), %%random:uniform/1
get_elmt(RandNum, L).
%--------------
const_test() ->
rock = const([]),
rock = const([paper, rock, paper]),
all_tests_passed.
const(OppPlays) ->
const(OppPlays, fun(_X) -> 1 end). %Necessary to give all the Strategies the
%same interface for testing.
const(OppPlays, RandFunc) ->
Strat = rand_from([fun rps:rock/1], RandFunc),
Strat(OppPlays).
%---------
%% Can't test this:
%%
%% rand(Ps) ->
%% Plays = plays(),
%% Rand = random:uniform(len(Plays)),
%% get_elmt(Rand, Plays).
rand_test() ->
%loop(N, Responses, Strategy, OppPlays)
Responses = plays(),
OppPlays1 = [],
loop(10, Responses, fun rps:rand/2, OppPlays1),
OppPlays2 = [paper, rock, rock, scissors], %Irrelevant.
loop(10, Responses, fun rps:rand/2, OppPlays2),
all_tests_passed.
rand(OppPlays) ->
rand(OppPlays, fun random:uniform/1). %I implemented rand/2, so that I could test
%rand/2 by passing in a deterministic RandFunc.
rand(_, RandFunc) -> %Also, handles empty list of opponent plays.
rand_from(plays(), RandFunc).
%------------
cycle_test() ->
rock = cycle([]),
paper = cycle([rock]),
scissors = cycle([paper]),
rock = cycle([scissors]),
all_tests_passed.
%Algorithm: in the plays() list return the play after the index
%position of the opponent's play:
cycle(OppPlays) ->
cycle(OppPlays, fun random:uniform/1). %Necessary to give all Strategies the same
%two arg interface for testing.
cycle(OppPlays, RandFunc) when is_function(RandFunc) ->
cycle(OppPlays, plays()); %Get rid of the RandFunc.
cycle([], [Play|_Plays]) -> %No opponent plays, response is first play in plays(), i.e. rock.
Play;
cycle([P|_Ps], [P|[]]) -> %Opponent's play matches last one in plays(), response is first play.
[Response|_] = plays(),
Response;
cycle([P|_Ps], [P|Plays]) -> %Response is next play after opponent's play.
[Response|_] = Plays,
Response;
cycle(Ps, [_|Plays]) ->
cycle(Ps, Plays).
%--------------
least_freq_test() ->
%loop(N, Responses, Strategy, OppPlays)
OppPlays = [],
Responses4 = lists:map(fun rps:beats/1, plays() ),
loop(10, Responses4, fun rps:least_freq/2, OppPlays),
OppPlays1 = [rock, scissors, paper, rock, scissors],
Responses1 = [beats(paper)], %paper is least frequent in OppPlays1
loop(10, Responses1, fun rps:least_freq/2, OppPlays1),
OppPlays2 = [rock, paper, paper, scissors, scissors],
Responses2 = [beats(rock)], % rock is least frequent in OppPlays2.
loop(10, Responses2, fun rps:least_freq/2, OppPlays2),
OppPlays3 = [scissors],
Responses3 = [beats(rock), beats(paper)],
% OppPlays = [scissors] => paper, rock will have freqs of 0
% least_freq calls get_freqs(), which returns the order: scissors, paper, rock.
% best frequencies will reverse those again => rock, paper
loop(10, Responses3, fun rps:least_freq/2, OppPlays3),
all_tests_passed.
least_freq(OppPlays) ->
least_freq(OppPlays, fun random:uniform/1). %This allows me to test least_freq/2
least_freq([], RandFunc) ->
%rand([], RandFunc) %Removed => couldn't test.
Responses = lists:map(
fun rps:beats/1,
plays()
),
rand_from(Responses, RandFunc);
least_freq(OppPlays, RandFunc) ->
MinFunc = fun(X, Y) -> %Compare the simplicity of an if-stmt to the
if %nested case-stmts that do the same thing below.
X<Y -> repl;
X=:=Y -> add;
X>Y -> skip
end
end,
MinFreqs = best_freqs( get_freqs(OppPlays), MinFunc ), %There could be more than one...
{Play, _Freq} = rand_from(MinFreqs, RandFunc), %so pick a random min frequency.
beats(Play).
%--------------
get_freqs_test() ->
[{scissors,0}, {paper, 0}, {rock, 0}] = get_freqs([]),
[{scissors,1}, {paper, 1}, {rock, 1}] = get_freqs([rock, paper, scissors]),
[{scissors,0}, {paper, 2}, {rock, 2}] = get_freqs([rock, paper, rock, paper]),
[{scissors,2}, {paper, 0}, {rock, 1}] = get_freqs([scissors, scissors, rock]),
[{scissors,0}, {paper, 2}, {rock, 1}] = get_freqs([paper, rock, paper]),
all_tests_passed.
get_freqs(OppPlays) ->
get_freqs(plays(), [], OppPlays).
get_freqs([], Counts, _OppPlays) ->
Counts;
get_freqs([P|Ps], Counts, OppPlays) ->
Count = count(P, OppPlays),
get_freqs(Ps, [{P, Count} | Counts], OppPlays).
%----------
best_freqs_test() ->
%Collect minimum frequencies:
MinFunc = fun(X, Y) ->
case X<Y of
true -> repl;
false -> case X>Y of
true -> skip;
false -> add
end
end
end,
%Collect maximum frequencies:
MaxFunc = fun(X, Y) ->
case X<Y of
true -> skip;
false -> case X>Y of
true -> repl;
false -> add
end
end
end,
[{b,1}] = best_freqs([{a,2},{b,1},{c,3}], MinFunc),
[{c,1}, {b,1}] = best_freqs([{a,2},{b,1},{c,1}], MinFunc),
[{c,1}, {b,1}, {a,1}] = best_freqs([{a,1},{b,1},{c,1}], MinFunc),
[{c,3}] = best_freqs([{a,2},{b,1},{c,3}], MaxFunc),
[{c,2}, {a,2}] = best_freqs([{a,2},{b,1},{c,2}], MaxFunc),
[{c,1}, {b,1}, {a,1}] = best_freqs([{a,1},{b,1},{c,1}], MaxFunc),
all_tests_passed.
best_freqs([X|Xs], CompareCounts) ->
best_freqs(Xs, CompareCounts, [X]). %Start off by choosing the first element
%as the one with the "best" count.
best_freqs([], _CompareCounts, Bests) ->
Bests;
best_freqs([ {_Name, Count}=X | Xs], CompareCounts, [ {_BestName, BestCount} | _]=Bests) ->
case CompareCounts(Count, BestCount) of
repl -> best_freqs(Xs, CompareCounts, [X]);
add -> best_freqs(Xs, CompareCounts, [X|Bests]);
skip -> best_freqs(Xs, CompareCounts, Bests)
end.
%-----------------
most_freq_test() ->
OppPlays1 = [rock, scissors, paper, rock, scissors, rock],
Responses1 = [beats(rock)], %Most freq in OppPlays1 is rock.
loop(10, Responses1, fun rps:most_freq/2, OppPlays1),
OppPlays2 = [rock, paper, paper, scissors],
Responses2 = [beats(paper)], %Most freq in OppPlays2 is paper.
loop(10, Responses2, fun rps:most_freq/2, OppPlays2),
OppPlays3 = [scissors], %=> paper, rock will have freqs of 0.
Responses3 = [beats(scissors)], %Most freq in OppPlays3 is scissors.
loop(10, Responses3, fun rps:most_freq/2, OppPlays3),
OppPlays4 = [], % most freq => rock, paper, scissors
%get_freqs => scissors, paper, rock
%best_freqs => rock, paper, scissors
Responses4 = [beats(rock), beats(paper), beats(scissors)], %Must be in right order!
loop(3, Responses4, fun rps:most_freq/2, OppPlays4),
all_tests_passed.
most_freq(OppPlays) ->
most_freq(OppPlays, fun random:uniform/1).
most_freq([], RandFunc) ->
%rand([], RandFunc). %Removed => couldn't test.
Responses = lists:map(
fun rps:beats/1,
plays()
),
rand_from(Responses, RandFunc);
most_freq(OppPlays, RandFunc) ->
MaxFunc = fun(X, Y) ->
if
X>Y -> repl;
X=:=Y -> add;
X < Y -> skip
end
end,
MaxFreqs = best_freqs( get_freqs(OppPlays), MaxFunc ),
{Play, _Count} = rand_from(MaxFreqs, RandFunc),
beats(Play).
%------------
apply_rand_strat_test() ->
RandFunc1 = fun(_X) -> 1 end,
RandFunc2 = fun(_X) -> 2 end,
RandFunc3 = fun(_X) -> 3 end,
Strats = [fun rps:no_repeat/1, fun rps:cycle/1, fun rps:least_freq/1],
Plays = [rock, paper],
%Need to specify module name for pattern match to work:
Strat1 = fun rps:no_repeat/1,
Strat1 = apply_rand_strat(Strats, Plays, RandFunc1),
Strat2 = fun rps:cycle/1,
Strat2 = apply_rand_strat(Strats, Plays, RandFunc2),
Strat3 = fun rps:least_freq/1,
Strat3 = apply_rand_strat(Strats, Plays, RandFunc3),
all_tests_passed.
apply_rand_strat(Ss, Ps) when length(Ss)>0 ->
apply_rand_strat(Ss, Ps, fun random:uniform/1).
apply_rand_strat(Ss, _Ps, RandFunc) ->
rand_from(Ss, RandFunc).
%-------------
apply_best_strat_test() ->
Strats1 = [fun rps:cycle/2, fun rps:most_freq/2, fun rps:const/2],
RandFunc1 = fun(_X) -> 1 end,
Plays1 = [rock, paper, rock],
%cycle([]) => rock, rock v. (last)rock => 0
%cycle[[rock]) => paper, paper v. paper => 0
%cycle([paper, rock]) => scissors, scissors v. rock => -1
%
%m_f([]) => All are "best" freqs, and choosing with RandFunc1 => beats(rock),
% paper v. (last)rock => +1
%m_f([rock]) => beats(rock), paper v. paper => 0
%m_f([paper, rock]) => get_freqs() is always in the same order(the reverse
% of plays(): scissors, paper, rock; then best_freqs()
% reverses its results, so most freq in this case choosing
% with RandFunc1 will be rock => paper, paper v. rock => +1
%
%const([]) => rock, rock v. (last)rock => 0
%cons([rock]) => rock, rock v. paper => -1
%const([paper, rock]) => rock, rock v. rock => 0
Expected1 = rps:most_freq(Plays1, RandFunc1),
Expected1 = apply_best_strat(Strats1, Plays1, RandFunc1),
Plays2 = [scissors, paper, rock],
%cycle([]) -> rock, rock v. last(rock) => 0
%cycle([rock]) -> rock, rock v. paper => -1
%cycle([paper,rock]) -> scissors v. scissors => 0
%
%m_f([]) => based on RandFunc1 => beat(rock), paper v. rock => +1
%m_f([rock]) => beat(rock), paper v. paper => 0
%m_f([paper, rock]) => beat(rock) => paper, paper v. scissors => -1
%
%const([]) => rock, rock v. rock => 0
%const([rock]) => rock, rock v. paper => -1
%const([paper, rock]) => rock, rock v. scissors => +1
%Ss get reversed by apply_best_strategy() before picking best strategy.
%Based on RandFunc1 first S in reversed best Ss will be best strat.
Expected2 = rps:const(Plays2, RandFunc1),
Expected2 = apply_best_strat(Strats1, Plays2, RandFunc1),
Strats3 = [fun rps:rand/2, fun rps:no_repeat/2, fun rps:least_freq/2],
Plays3 = [paper, paper, paper],
%rand([]) => rock, rock v. paper => -1
%rand([paper]) => rock, rock v. paper => -1
%rand([paper, paper]) => rock, rock v paper => -1
%
%no_repeat([]) -> rock, rock v. paper => -1
%no_repeat([paper]) => scissors, scissors v. paper => 1
%no_repeat([paper, paper]) => scissors, scissors v. paper => 1
%
%l_f([]) => beat(rock) => paper, paper v. paper => 0
%l_f([paper]) => beat(rock) => paper, paper v. paper => 0
%l_f([paper, paper]) => beat(rock) => paper, paper v. paper => 0
Expected3 = rps:no_repeat(Plays3, RandFunc1),
Expected3 = apply_best_strat(Strats3, Plays3, RandFunc1),
all_tests_passed.
% Variables:
%
% Ss => Strategies
% Ps => Opponent's Plays
% Score => {StrategyFunc, Score}
%
apply_best_strat(Ss, []) when length(Ss)>0 ->
apply_best_strat(Ss, [], fun random:uniform/1).
apply_best_strat(Ss, [], RandFunc) when length(Ss)>0 ->
Strat = rand_from(Ss, RandFunc),
Strat([]);
apply_best_strat(Ss, Ps, RandFunc) when length(Ss)>0 ->
Scores = apply_best_strat(Ss, Ps, RandFunc, []),
MaxFunc = fun(X, Y) ->
if
X>Y -> repl;
X=:=Y -> add;
X<Y -> skip
end
end,
{BestStrat, _Score} = rand_from( %Pick first "best" strategy. No! Let's get a random one.
best_freqs(Scores, MaxFunc),
RandFunc
),
BestStrat(Ps, RandFunc).
apply_best_strat([], _Ps, _RandFunc, Scores) ->
Scores;
apply_best_strat([S|Ss], Ps, RandFunc, Scores) ->
Score = backTest(S, Ps, RandFunc), %Funky function name so that eunit doesn't consider it a test.
apply_best_strat(Ss, Ps, RandFunc, [Score|Scores]).
backTest_test() ->
%Test const/2
% const() => rock
RandFunc1 = fun(_X) -> 1 end,
Score1 = {fun rps:const/2, -1},
Score1 = backTest(fun rps:const/2,[paper], RandFunc1),
Score2 = {fun rps:const/2, +1},
Score2 = backTest(fun rps:const/2, [scissors], RandFunc1),
Score3 = {fun rps:const/2, -2},
Score3 = backTest(fun rps:const/2, [paper, rock, paper], RandFunc1),
Score4 = {fun rps:const/2, 0},
Score4 = backTest(fun rps:const/2, [rock, scissors, paper], RandFunc1),
Score5 = {fun rps:const/2, +2},
Score5 = backTest(fun rps:const/2, [scissors, rock, scissors], RandFunc1),
%Test least_freq/2:
History1 = [rock, paper],
Plays1 = [rock],
%least_freq(History1) => scissors, so Response would be beats(scissors) => rock,
%which draws with the rock in Plays1, thus Score = {least_freq, 0}
Score6 = {fun rps:least_freq/2, 0},
Score6 = backTest(fun rps:least_freq/2, Plays1, RandFunc1, History1, []),
History2 = [rock, paper],
Plays2 = [scissors],
Score7 = {fun rps:least_freq/2, 1},
Score7 = backTest(fun rps:least_freq/2, Plays2, RandFunc1, History2, []),
History3 = [rock, paper],
Plays3 = [paper, paper],
Score8 = {fun rps:least_freq/2, -2},
Score8 = backTest(fun rps:least_freq/2, Plays3, RandFunc1, History3, []),
History4 = [],
Plays4 = [rock, paper],
%% l_f([]) => beat(rock) => paper, paper v. paper => 0
%% l_f([paper]) => paper, paper v. rock => +1
%% l_f([rock, paper]) -> ends
%% Total => 0
Score9 = {fun rps:least_freq/2, 1},
Score9 = backTest(fun rps:least_freq/2, reverse(Plays4), RandFunc1, History4, []),
%Test most_freq/2:
History5 = [],
Plays5 = [paper, rock, scissors],
%% m_f([]) => beat(rock), paper v. scissors => -1
%% m_f([scissors]) => beat(scissors) => rock, rock v. rock => 0
%% m_f([rock, scissors]) => beat(rock) => paper v. paper => 0
%% m_f([rock, paper]) -> ends
%% Total => -1
Score10 = {fun rps:most_freq/2, -1},
Score10 = backTest(fun rps:most_freq/2, reverse(Plays5), RandFunc1, History5, []),
%Test cycle/2:
History6 = [],
Plays6 = [paper, rock, scissors],
%% cycle([]) => rock, rock v. scissors => +1
%% cycle([scissors]) => rock, rock v. rock => 0
%% cycle([rock, scissors]) => paper v. paper => 0
%% cycle([rock, paper]) -> ends
%% Total => +1
Score11 = {fun rps:cycle/2, +1},
Score11 = backTest(fun rps:cycle/2, reverse(Plays6), RandFunc1, History6, []),
%Test rand/2:
%rand([]) => rock, rock v. scissors => +1
%rand([scissors]) => rock, rock v. rock => 0
%rand([rock, scissors]) => rock, rock v. paper => -1
Score12 = {fun rps:rand/2, 0},
Score12 = backTest(fun rps:rand/2, reverse(Plays6), RandFunc1, History6, []),
all_tests_passed.
backTest(S, Ps, RandFunc) -> %S - Strategy, Ps - OppPlays
backTest(S, reverse(Ps), RandFunc, [], []).
backTest(S, [], _RandFunc, _History, Pairs) ->
%Process the Pairs accumulator:
Score = lists:sum(lists:map(
fun({R, P}) -> outcome(result(R, P) ) end, %R => Response based on opponent's History,
Pairs %Acummulator here! %P => opponent's current Play
)),
{S, Score}; %Return Strategy with its backTest() Score.
backTest(S, [P|Ps], RandFunc, History, Pairs) ->
backTest(S, Ps, RandFunc, [P|History], [ {S(History, RandFunc), P} | Pairs]).
%------Utility functions:
get_elmt_test() ->
a = get_elmt(1, [a, b, c]),
b = get_elmt(2, [a, b, c]),
c = get_elmt(3, [a, b, c]),
all_tests_passed.
get_elmt(1, [P|_]) ->
P;
get_elmt(N, [_P|Ps]) when N>=1 ->
get_elmt(N-1, Ps).
%-----------------
reverse_test() ->
[] = reverse([]),
[2, 1] = reverse([1, 2]),
[1, 2, 3] = reverse([3, 2, 1]),
all_tests_passed.
reverse(L) -> reverse(L, []).
reverse([], Acc) ->
Acc;
reverse([X|Xs], Acc) ->
reverse(Xs, [X|Acc]).
%---------
member_test() ->
false = member(3, []),
false = member(3, [1, 2, 4]),
false = member(-1, [-2, 0, -2, -3]),
true = member(3, [3]),
true = member(3, [1, 1, 3, 1, 2]),
true = member(3, [2,3]),
all_tests_passed.
member(_, []) -> false;
member(N, [N|_]) -> true;
member(N, [_|Xs]) ->
member(N, Xs).
%-----------
len_test() ->
0 = len([]),
1 = len([-1]),
2 = len([0, -1]),
3 = len([1, -1, 0]),
all_tests_passed.
len(L) ->
len(L, 0).
len([], Count) ->
Count;
len([_|Xs], Count) ->
len(Xs, Count+1).
%----------
count_test() ->
0 = count(3, []),
1 = count(-1, [1, -1, 2]),
2 = count(0, [1, 0, -1, 0, -2, -1]),
3 = count(1, [1, 0, 1, 3, 1]),
4 = count(1, [1, 1, 1, 1]),
all_tests_passed.
count(_, []) -> 0;
count(N, L) ->
count(N, L, 0).
count(_, [], Count) ->
Count;
count(N, [N|Xs], Count) ->
count(N, Xs, Count+1);
count(N, [_|Xs], Count) ->
count(N, Xs, Count).
%---------
my_hd_test() ->
a = my_hd([a, b, c]),
b = my_hd([b]),
all_tests_passed.
my_hd([X|_]) -> X.
%----------
print(Term) ->
io:format("~w~n", [Term]).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment