From 7ac6005daff78fce414264685ec1fe4416fd06be Mon Sep 17 00:00:00 2001 From: Correl Roush Date: Mon, 2 Jul 2012 22:05:05 -0400 Subject: [PATCH] Set and sequence detection --- include/riichi.hrl | 5 +++++ src/riichi_hand.erl | 43 ++++++++++++++++++++++++++++++++++++++ test/riichi_hand_tests.erl | 24 +++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 src/riichi_hand.erl create mode 100644 test/riichi_hand_tests.erl diff --git a/include/riichi.hrl b/include/riichi.hrl index 9b45447..a8d044e 100644 --- a/include/riichi.hrl +++ b/include/riichi.hrl @@ -13,3 +13,8 @@ tile, open=true }). + +-record(seq, { + tiles, + open=true +}). diff --git a/src/riichi_hand.erl b/src/riichi_hand.erl new file mode 100644 index 0000000..c7419f1 --- /dev/null +++ b/src/riichi_hand.erl @@ -0,0 +1,43 @@ +-module(riichi_hand). + +-include("riichi.hrl"). + +-compile([export_all]). + + +find_sets(Tiles) -> + Unique = sets:to_list(sets:from_list(Tiles)), + [#set{count=length(lists:filter(fun(X) -> X == T end, Tiles)), tile=T, open=false} + || T <- Unique]. + +reorder_seqs(Tiles) -> + Unique = sets:to_list(sets:from_list(Tiles)), + lists:sort(Unique) ++ (Tiles -- Unique). + +find_seqs(Tiles) -> + find_seqs(reorder_seqs(Tiles), {[], []}). + +find_seqs([], {Seqs, Rest}) -> + {lists:sort(Seqs), lists:sort(Rest)}; + +find_seqs([T1 = #tile{suit=Suit}, T2 = #tile{suit=Suit}, T3 = #tile{suit=Suit} | Tiles], {Seqs, Rest}) + when T2#tile.value =:= (T1#tile.value + 1) + andalso T3#tile.value =:= (T2#tile.value + 1) -> + find_seqs(reorder_seqs(Tiles), {[#seq{tiles=[T1, T2, T3], open=false} | Seqs], Rest}); + +find_seqs([T | Tiles], {Seqs, Rest}) -> + find_seqs(Tiles, {Seqs, [T | Rest]}). + +perms([]) -> [[]]; +perms(L) -> [[H|T] || H <- L, T <- perms(L--[H])]. + +combinations(0, _) -> [[]]; +combinations(_, []) -> []; +combinations(N, [X|XS]) -> [[X|YS] || YS <- combinations(N-1, XS)] ++ combinations(N, XS). + +find_hands(Tiles) -> + find_hands(Tiles, []). +find_hands([], Hands) -> + Hands; +find_hands([_T | _Remaining] = Tiles, Hands) -> + [#hand{tiles=Tiles} | Hands]. diff --git a/test/riichi_hand_tests.erl b/test/riichi_hand_tests.erl new file mode 100644 index 0000000..1a8eb28 --- /dev/null +++ b/test/riichi_hand_tests.erl @@ -0,0 +1,24 @@ +-module(riichi_hand_tests). + +-include("riichi.hrl"). +-include_lib("eunit/include/eunit.hrl"). + +find_sets_test() -> + Tiles = [#tile{suit=man, value=V} || V <- lists:seq(1,8)], + Expected = {[ + #seq{tiles=[#tile{suit=man, value=V} || V <- lists:seq(1,3)], open=false}, + #seq{tiles=[#tile{suit=man, value=V} || V <- lists:seq(4,6)], open=false} + ], + [#tile{suit=man, value=V} || V <- lists:seq(7,8)] + }, + ?assertEqual(Expected, riichi_hand:find_seqs(Tiles)). +find_duplicate_sets_test() -> + Tiles = [#tile{suit=man, value=V} || V <- lists:seq(1,3), _ <- lists:seq(1,3)] ++ + [#tile{suit=man, value=4} || _ <- [1,2]], + Expected = {[ + #seq{tiles=[#tile{suit=man, value=V} || V <- lists:seq(1,3)], open=false} + || _ <- [1,2,3] + ], + [#tile{suit=man, value=4} || _ <- [1,2]] + }, + ?assertEqual(Expected, riichi_hand:find_seqs(Tiles)).