ptrelford

Poker scoring

Apr 22nd, 2012
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 3.46 KB | None | 0 0
  1. -module(poker).
  2. -export([compare/2]).
  3.  
  4. is_flush([{_,H}|T]) -> lists:all(fun({_,Suit})-> Suit =:= H end, T).
  5.  
  6. ordinal($2) -> 2;
  7. ordinal($3) -> 3;
  8. ordinal($4) -> 4;
  9. ordinal($5) -> 5;
  10. ordinal($6) -> 6;
  11. ordinal($7) -> 7;
  12. ordinal($8) -> 8;
  13. ordinal($9) -> 9;
  14. ordinal($T) -> 10;
  15. ordinal($J) -> 11;
  16. ordinal($Q) -> 12;
  17. ordinal($K) -> 13;
  18. ordinal($A) -> 14.
  19.  
  20. is_five_high_straight([{$2,_},{$3,_},{$4,_},{$5,_},{$A,_}]) -> true;
  21. is_five_high_straight(_) -> false.
  22. is_straight(Hand) ->
  23.  [H|T] = [ordinal(Rank)||{Rank,_}<-Hand],
  24.  Orders = lists:zip(T,[1,2,3,4]),
  25.  lists:all(fun({Ordinal,Offset}) -> Ordinal =:= H + Offset end, Orders).
  26.  
  27. kinds(Hand) ->
  28.  Counts=lists:foldl(fun({Rank,_},D)-> dict:update_counter(Rank,1,D) end,dict:new(),Hand),
  29.  Kinds=dict:to_list(Counts),
  30.  lists:reverse(lists:keysort(2,Kinds)).
  31.  
  32. score(Hand) ->
  33.  Sorted=lists:keysort(1,Hand),
  34.  {HighRank,_}=lists:last(Sorted),
  35.  IsFlush = is_flush(Sorted),
  36.  IsStraight = is_straight(Sorted),
  37.  IsFiveHighStraight = is_five_high_straight(Sorted),
  38.  case kinds(Sorted) of
  39.   _ when IsFlush andalso IsFiveHighStraight -> {9,"straight flush",fun compare_rank/2,$5};
  40.   _ when IsFlush andalso IsStraight -> {9,"straight flush",fun compare_rank/2,HighRank};
  41.   [{Rank,4},{_,1}] -> {8,"four of a kind",fun compare_rank/2,Rank};
  42.   [{Rank,3},{_,2}] -> {7,"full house",fun compare_rank/2,Rank};
  43.   _ when IsFlush -> {6,"flush",fun compare_ranks/2,[R||{R,_}<-Hand]};
  44.   _ when IsFiveHighStraight -> {5,"straight",fun compare_rank/2,$5};
  45.   _ when IsStraight -> {5,"straight",fun compare_rank/2,HighRank};
  46.   [{Rank,3}|_] -> {4,"three of a kind",fun compare_rank/2,Rank};
  47.   [{P1,2},{P2,2},{R,1}] -> {3,"two pairs",fun compare_two_pairs/2,{[P1,P2],R}};
  48.   [{P,2},{R1,_},{R2,_},{R3,_}] -> {2,"pair",fun compare_one_pair/2,{P,[R1,R2,R3]}};
  49.   _ -> {1,"high card",fun compare_ranks/2,[R||{R,_}<-Hand]}
  50.  end.
  51.  
  52. compare_one_pair({PB,TB},{PW,TW}) ->
  53.  case compare_rank(PB,PW) of
  54.   tie -> compare_ranks(TB,TW);
  55.   {A,B} -> {A,B}
  56.  end.
  57.  
  58. compare_two_pairs({PB,TB},{PW,TW}) ->
  59.  case compare_ranks(PB,PW) of
  60.   tie -> compare_rank(TB,TW);
  61.   {A,B} -> {A,B}
  62.  end.
  63.  
  64. compare_rank(RankB,RankW) ->
  65.  OrdinalB = ordinal(RankB),
  66.  OrdinalW = ordinal(RankW),
  67.  if
  68.   OrdinalB  >  OrdinalW -> {black,RankB};
  69.   OrdinalB  <  OrdinalW -> {white,RankW};
  70.   OrdinalB =:= OrdinalW -> tie
  71.  end.
  72.  
  73. compare_ranks(HandB,HandW) ->
  74.  Order=fun(Hand)->lists:reverse(lists:keysort(2,[{R,ordinal(R)}||R<-Hand])) end,
  75.  Hands=lists:zip(Order(HandB),Order(HandW)),
  76.  Diff=lists:dropwhile(fun({{_,A},{_,B}})->A=:=B end, Hands),
  77.  case Diff of
  78.   [] -> tie;
  79.   [{{RB,OB},{_ ,OW}}|_] when OB > OW -> {black,RB};
  80.   [{{_ ,OB},{RW,OW}}|_] when OB < OW -> {white,RW}
  81.  end.
  82.  
  83. compare(Black,White) ->
  84.  Parse=fun(Tokens)->[{R,S}||[R,S]<-string:tokens(Tokens, " ")] end,
  85.  {RankB,CategoryB,FunB,ValueB} = score(Parse(Black)),
  86.  {RankW,CategoryW,_   ,ValueW} = score(Parse(White)),
  87.  if
  88.   RankB  >  RankW -> "Black wins. - with " ++ CategoryB;
  89.   RankB  <  RankW -> "White wins. - with " ++ CategoryW;
  90.   RankB =:= RankW ->
  91.    case FunB(ValueB,ValueW) of
  92.     {black,Rank} -> "Black wins. - with " ++ CategoryB ++ ": " ++ [Rank];
  93.     {white,Rank} -> "White wins. - with " ++ CategoryW ++ ": " ++ [Rank];
  94.     tie          -> "Tie."
  95.    end
  96.   end.
  97.  
  98. %%Test cases
  99. %%poker:compare("2H 3D 5C 9C KD", "2C 3H 4S 8C AH").
  100. %%poker:compare("2H 4C 4C 2D 4H", "2S 8S AS QS 3S").
  101. %%poker:compare("2H 3D 5S 9C KD", "2C 3H 4S 8C KH").
  102. %%poker:compare("2H 3D 5S 9C KD", "2C 3H 5C 9S KH").
Advertisement
Add Comment
Please, Sign In to add comment