Interestingly, this is the first time I've tried to write a program that ranks poker hands. My code isn't complete .. for one, it doesn't account for 2nd level ties (e.g., 7 7 6 6 5 compared with 7 7 6 6 4).
However, in taking the code as far as I have, I discovered some things that you really ought to consider. Most importantly, ranking must be done using whole numbers .. otherwise you run into numeric precision issues. That is always a risk, with computers, attempting to do comparisons of calculations as if they were done using base 10 math.
Anyhow, here is what I've done so far:
%let decksize=52;
%let handsize=5;
%let nsims=10000;
%let nhands=5;
/*missing the following*/
%let seed=0;
data _null_;
ncards=&handsize*&nhands;
call symput("ncards", ncards);
run;
data deck;
call streaminit(&seed);
/* set suit a card values*/
/* suits 1=clubs 2=diamonds 3=hearts 4=spades*/
do suit=1 to 4;
do value=2 to 14;
order=rand("uniform");
output;
end;
end;
run;
proc sort data=deck;
by order;
run;
data hands (drop=value suit order hand cards);
array handv(&handsize.);
array hands(&handsize.);
/* deal for each player */
do hand=1 to &nhands.;
do cards=1 to &handsize.;
set deck;
handv(cards)=value;
hands(cards)=suit;
end;
call sortn(of hands(*));
call sortn(of handv(*));
output;
end;
stop;
run;
/*For testing purposes only: create test hands dataset
data hands;
input handv1-handv5 hands1-hands5;
cards;
2 3 4 5 14 1 1 1 1 1
10 11 12 13 14 1 1 1 1 1
9 10 11 12 13 4 4 4 4 4
8 10 11 12 13 4 4 4 4 4
7 9 9 9 9 1 1 2 3 4
4 5 6 7 8 1 1 2 3 4
2 3 4 4 4 1 1 2 3 4
5 6 6 6 7 1 2 2 3 4
8 9 9 9 10 10 2 2 3 3 4
5 6 7 7 7 1 2 3 3 4
2 5 5 6 6 2 2 3 3 4
2 3 4 4 5 1 1 1 2 3
9 10 11 12 14 1 2 2 3 4
4 5 6 8 9 1 1 1 2 3
;
*/
data game;
set hands;
array handv(&handsize.) handv1-handv5;
array hands(&handsize.) hands1-hands5;
/*create ranks based on*/
/*900=Straight Flush*/
/*800=Four of a Kind*/
/*700=Full House*/
/*600=Flush*/
/*500=Straight*/
/*400=Three of a kind*/
/*300=Two pair*/
/*200=Pair*/
/*100=High card*/
rank=0;
/* check for flush */
if hands(1) eq hands(5) then rank=600+handv(5);
/* check for straight or straight flush */
if (handv(5)-handv(4)) eq 1 and
(handv(4)-handv(3)) eq 1 and
(handv(3)-handv(2)) eq 1 and
(handv(2)-handv(1)) eq 1 then do;
if rank gt 600 then rank=900+handv(5);
else rank=500+handv(5);
end;
/* check for an Ace thru 5 straight or straight flush*/
else if handv(5) eq 14 and
handv(4) eq 5 and
handv(3) eq 4 and
handv(2) eq 3 and
handv(1) eq 2 then do;
if rank gt 600 then rank=900+handv(4);
else rank=500+handv(4);
end;
if rank lt 500 then do;
/* check for four of a kind */
if (sum(of handv(*))-handv(1)) eq (4*handv(5)) or
(sum(of handv(*))-handv(5)) eq (4*handv(1)) then
rank=800+handv(2);
/* check for full house */
else if (handv(1) eq handv(2) and handv(3)=handv(5)) or
(handv(1)=handv(3) and handv(4)=handv(5)) then
rank=700+handv(3);
/* check for three of a kind */
else if (sum(of handv(*))-handv(5)-handv(4)) eq (3*handv(1)) or
(sum(of handv(*))-handv(1)-handv(5)) eq (3*handv(2)) or
(sum(of handv(*))-handv(1)-handv(2)) eq (3*handv(3)) then
rank=400+handv(3);
/* check for two pairs */
else if (handv(1) eq handv(2) and handv(3) eq handv(4)) or
(handv(1) eq handv(2) and handv(4) eq handv(5)) or
(handv(2) eq handv(3) and handv(4) eq handv(5)) then
rank=300+handv(4);
/* check for one pair */
else if (handv(1) eq handv(2)) or
(handv(2) eq handv(3)) or
(handv(3) eq handv(4)) or
(handv(4) eq handv(5)) then do;
if handv(1) eq handv(2) then rank=200+handv(2);
else if handv(2) eq handv(3) then rank=200+handv(3);
else if handv(3) eq handv(4) then rank=200+handv(4);
else if handv(4) eq handv(5) then rank=200+handv(5);
end;
/* check for high card */
else rank=100+handv(4);
end;
run;
Of course, the above isn't tested for accuracy .. that part is up to you.
Art, CEO, AnalystFinder.com
... View more