I want to create an algorithm that allocates a player's hand in a poker game a value. There is only one way I can see this working:
I create a table generating every poker hand (there are approx. 2.6m distinct hands) and then perform an algorithm to allocate a ranking to each hand (there are only approx. 7600 poker values). The table might look something like this:
I'm not sure how I would go about generating the 2.6 million hands such that they are all unique. I know it is probably straighforward but I am used to generating data sets in sas.
Card 1 | Card 2 | Card 3 | Card 4 | Card 5 | Rank |
---|---|---|---|---|---|
10S | JS | QS | KS | AS | 1 |
10C | JC | QC | KC | AC | 1 |
9S | 10S | JS | QS | KS | 2 |
Once I have the first 5 columns, I think the only way of generating the rank is to do a series of steps that determine what rank of hand the player holds i.e. loads of steps to check if the hand is a flush, straight etc.)
Once this table has been generated I will use it as a reference table to check hands against. In another part of the code I will simulate a poker game between x players. I am also looking for help on how to check a player's 2 cards and the 5 common cards and allocate a rank based on the first table. So the code would need to pick the best 5 card combination out of 7 and then lookup this value in the table above.
Player Card 2 | Player Card 1 | Common Card 1 | Common Card 2 | Common Card 3 | Common Card 4 | Common Card 5 | Rank |
---|---|---|---|---|---|---|---|
9H | 10H | 2S | 3C | JD | 4D | 3D | 1134 |
KS | KC | 2D | 7H | JC | 6S | QS | 65 |
I know this can be done in excel but excel is too slow. I need a program that can simulate 1000s of poker games and I think SAS is far superior for this task. But I'm a bit concerned that it will still be too slow if it needs to read a table with 2.6m rows to allocate a rank for every hand. The poker games I'm trying to simulate might only involve 50 hands altogether but hat means looking up the rank table 300 times. I suppose I won't know until I've created the algorithm but It is a concern.
Any help on this would be very much appreciated
Well, I came from non-western culture where Poker has different rules. Since it took me some effort to know Poker rules using Wiki, I will probably use it as the material for a paper for next year SESUG. All of the business requirements are obtained from Wikipedia: List of poker hands - Wikipedia, the free encyclopedia
/*I use 14 to address 'A' for the simplicity of coding. There are 2,598,960 distinct hands,
out of which, there are 7,462 distinct scores, The whole process runs less than 10 secs on my
4x core pc, win7, if you already have the hands, to rank 100 of them takes less than 1 sec*/
/*TO GENERATE 52 CARDS POOL*/
DATA CAT;
INPUT SUIT :$1. @@;
CARDS;
S C H D
;
DATA SEQ;
INPUT NUM :$2. @@;
CARDS;
14 13 12 11 10 09 08 07 06 05 04 03 02
;
PROC SQL NOPRINT;
SELECT DISTINCT QUOTE(CATS(SUIT,NUM)) INTO :HANDS SEPARATED BY ' ' FROM CAT, SEQ;
QUIT;
/*EMBED RANKING ALGORITHM INTO THE FOLLOWING MACRO*/
%MACRO SIM;
DO Z=1 TO 5;
FST(Z)=FIRST(C(Z));
NUM(Z)=INPUT(COMPRESS(C(Z),,'KD'),2.);
END;
CALL SORTC (OF FST(*));
CALL SORTN (OF NUM(*));
/*STRAIGHT FLUSH*/
IF FST(1)=FST(5) AND NUM(5)-NUM(4)=1 AND NUM(4)-NUM(3)=1 AND NUM(3)-NUM(2)=1 AND NUM(2)-NUM(1)=1 THEN
DO;
RANK1=9;
RANK2=NUM(5);
RANK3=999;
RANK4=999;
RANK5=999;
RANK6=999;
END;
ELSE IF FST(1)=FST(5) AND NUM(1)=2 AND NUM(2)=3 AND NUM(3)=4 AND NUM(4)=5 AND NUM(5)=14 THEN DO;
RANK1=9;
RANK2=NUM(4);
RANK3=999;
RANK4=999;
RANK5=999;
RANK6=999;
END;
/*FOUR OF A KIND*/
ELSE IF NUM(1)=NUM(4) OR NUM(2)=NUM(5) THEN
DO;
RANK1=8;
IF NUM(1)=NUM(4) THEN
DO;
RANK2=NUM(1);
RANK3=NUM(5);
RANK4=999;
RANK5=999;
RANK6=999;
END;
ELSE IF NUM(2)=NUM(5) THEN
DO;
RANK2=NUM(2);
RANK3=NUM(1);
RANK4=999;
RANK5=999;
RANK6=999;
END;
END;
/*FULL HOUSE*/
ELSE IF (NUM(1)=NUM(2) AND NUM(3)=NUM(5)) OR (NUM(1)=NUM(3) AND NUM(4)=NUM(5)) THEN
DO;
RANK1=7;
IF (NUM(1)=NUM(2) AND NUM(3)=NUM(5)) THEN
DO;
RANK2=NUM(3);
RANK3=NUM(1);
RANK4=999;
RANK5=999;
RANK6=999;
END;
ELSE IF (NUM(1)=NUM(3) AND NUM(4)=NUM(5)) THEN
DO;
RANK2=NUM(1);
RANK3=NUM(4);
RANK4=999;
RANK5=999;
RANK6=999;
END;
END;
/*FLUSH*/
ELSE IF FST(1)=FST(5) THEN
DO;
RANK1=6;
RANK2=NUM(5);
RANK3=NUM(4);
RANK4=NUM(3);
RANK5=NUM(2);
RANK6=NUM(1);
END;
/*STRAIGHT*/
ELSE IF NUM(5)-NUM(4)=1 AND NUM(4)-NUM(3)=1 AND NUM(3)-NUM(2)=1 AND NUM(2)-NUM(1)=1 THEN
DO;
RANK1=5;
RANK2=NUM(5);
RANK3=999;
RANK4=999;
RANK5=999;
RANK6=999;
END;
ELSE IF NUM(1)=2 AND NUM(2)=3 AND NUM(3)=4 AND NUM(4)=5 AND NUM(5)=14 THEN
DO;
RANK1=5;
RANK2=NUM(4);
RANK3=999;
RANK4=999;
RANK5=999;
RANK6=999;
END;
/*THREE OF A KIND*/
ELSE IF (NUM(1)=NUM(3) OR NUM(2)=NUM(4) OR NUM(3)=NUM(5)) THEN
DO;
RANK1=4;
IF NUM(1)=NUM(3) THEN
DO;
RANK2=NUM(1);
RANK3=NUM(5);
RANK4=NUM(4);
RANK5=999;
RANK6=999;
END;
IF NUM(2)=NUM(4) THEN
DO;
RANK2=NUM(2);
RANK3=NUM(5);
RANK4=NUM(1);
RANK5=999;
RANK6=999;
END;
IF NUM(3)=NUM(5) THEN
DO;
RANK2=NUM(3);
RANK3=NUM(2);
RANK4=NUM(1);
RANK5=999;
RANK6=999;
END;
END;
/*TWO PAIR*/
ELSE IF (NUM(1)=NUM(2) AND NUM(3)=NUM(4)) OR (NUM(1)=NUM(2) AND NUM(4)=NUM(5)) OR (NUM(2)=NUM(3) AND NUM(4)=NUM(5)) THEN
DO;
RANK1=3;
IF (NUM(1)=NUM(2) AND NUM(3)=NUM(4)) THEN
DO;
RANK2=NUM(3);
RANK3=NUM(1);
RANK4=NUM(5);
RANK5=999;
RANK6=999;
END;
IF (NUM(1)=NUM(2) AND NUM(4)=NUM(5)) THEN
DO;
RANK2=NUM(5);
RANK3=NUM(1);
RANK4=NUM(3);
RANK5=999;
RANK6=999;
END;
IF (NUM(3)=NUM(2) AND NUM(5)=NUM(4)) THEN
DO;
RANK2=NUM(5);
RANK3=NUM(3);
RANK4=NUM(1);
RANK5=999;
RANK6=999;
END;
END;
/*ONE PAIR*/
ELSE IF NUM(1)=NUM(2) OR NUM(2)=NUM(3) OR NUM(3)=NUM(4) OR NUM(4)=NUM(5) THEN
DO;
RANK1=2;
IF NUM(1)=NUM(2) THEN
DO;
RANK2=NUM(1);
RANK3=NUM(5);
RANK4=NUM(4);
RANK5=NUM(3);
RANK6=999;
END;
IF NUM(2)=NUM(3) THEN
DO;
RANK2=NUM(3);
RANK3=NUM(5);
RANK4=NUM(4);
RANK5=NUM(1);
RANK6=999;
END;
IF NUM(3)=NUM(4) THEN
DO;
RANK2=NUM(4);
RANK3=NUM(5);
RANK4=NUM(2);
RANK5=NUM(1);
RANK6=999;
END;
IF NUM(4)=NUM(5) THEN
DO;
RANK2=NUM(5);
RANK3=NUM(3);
RANK4=NUM(2);
RANK5=NUM(1);
RANK6=999;
END;
END;
/*HIGH CARD*/
ELSE
DO;
RANK1=1;
RANK2=NUM(5);
RANK3=NUM(4);
RANK4=NUM(3);
RANK5=NUM(2);
RANK6=NUM(1);
END;
%MEND;
/*SCORE ALL OF THE COMBINATIONS*/
data HANDS;
array c[5] $3;
array x[52] $3 (&HANDS.);
array i[5];
ARRAY NUM(5) num1-num5;
ARRAY FST(5) $ 1 fst1-fst5;
n=dim(x);
k=dim(i);
i[1]=0;
ncomb=comb(n,k);
do j=1 to ncomb;
call allcombi(n, k, of i
do h=1 to k;
c
end;
%SIM
OUTPUT;
end;
KEEP C: RANK: num:;
run;
/*ORDER AND RANK DISTINCT SCORES*/
PROC SORT DATA=HANDS OUT=HAND_SORT;
BY DESCENDING RANK1 DESCENDING RANK2 DESCENDING RANK3 DESCENDING RANK4 DESCENDING RANK5 DESCENDING RANK6;
RUN;
DATA RANKS (KEEP=RANK: ORDER);
SET HAND_SORT;
BY DESCENDING RANK1 DESCENDING RANK2 DESCENDING RANK3 DESCENDING RANK4 DESCENDING RANK5 DESCENDING RANK6;
IF FIRST.RANK6;
ORDER+1;
RUN;
/*RANDOM SAMPLE: CAN ALSO BE DONE USING DATA STEP*/
PROC SURVEYSELECT DATA=WORK.HANDS
OUT=WORK.SAMPLE (KEEP=C:)
METHOD=SRS
N=90000;
RUN;
/*RANK THE SAMPLE DATA, THERE ARE MANY WAYS FOR THIS KIND OF LOOK UP, HERE IS TO USE HASH() TABLE*/
DATA WANT;
IF _N_=1 THEN
DO;
IF 0 THEN
SET RANKS;
DECLARE HASH H(DATASET:'RANKS');
H.DEFINEKEY('RANK1', 'RANK2','RANK3','RANK4', 'RANK5','RANK6');
H.DEFINEDATA(ALL:'Y');
H.DEFINEDONE();
END;
SET SAMPLE;
array c[5] $3;
ARRAY NUM(5) num1-num5;
ARRAY FST(5) $ 1 fst1-fst5;
%SIM
RC=H.FIND();
KEEP C: ORDER;
run;
Update:
Got a PM saying that since I use '14' for ACE that I miscategorized 'Steel Wheel' and 'Wheel' (Meaning A-2-3-4-5 is still qualified for 'Straight') , hence the update.
Update 2:
FYI: Given OP has 300 games, 6 players and each for 50 plays, that counts for 90,000 hand. To rank them took less than 1 sec on my machine. It is really not a heavy-duty computing job by any means.
Maybe you should check call greycode() routine.But I don't know if it could handle 26 cards ,check documentation.
Xia Keshan
Generating the combinations is straightforward:
data all_combinations;
do card1=1 to 48;
do card2=card1+1 to 49;
do card3=card2+1 to 50;
do card4=card3+1 to 51;
do card5=card4+1 to 52;
output;
end;end;end;end;end;
run;
I'm assuming you can translate a number from 1 to 52 into a specific card in the deck. Assigning rankings to 2.6M hands might be a bit harder, but this should at least move you a step closer.
Good luck.
Hi Astounding
I've started writing the code for the poker hand evaluator. Basically the algorithm looks up 5 cards (in order of number e.g. 02S 03D 07H 12H 13D) and it is run through the code to check if it's a straight flush, 4 of a kind, full house etc. and a unique hand value is assigned to the hand. So for a royal flush, the value is 1 and four hands have this value, for a straight flush king high, the value is 2, and so on. I'm just wondering if my approach is too tedious and I'm overcomplicating things? I'm using lots of else do; end; and macros within macros and alhough I will get it out eventually, if there's a better approach I'll use it. Otherwise i'm happy to work away on the code below.
The dataset Sample is just a five column data set with the fields card1,card2,...,card5 with values in the form as above.
Thanks
I would post the code directly but I can't paste into these forums.
It looks like you're going to be doing a whole lot of splitting out of the codes they way you requested the cards to look.
It might be better to have two variables for each card, value and suit and possibly as numeric value 1-13 and 1-4 with appropriate formats to display as A, K, Q and J or C,D,H and S as needed.
I have a sneaking suspicion this project my be more amenable in IML, but that's a guess.
Hi Ballardw
I think for what I'm doing IML sounds like the way to go. I've downloaded the free SAS University edition as my company doesn't uses SAS 9.2 which does not have SAS/IML.
I also think from the feedback on the forums that a pairwise algorithm is the best apparoach to follow for evaluating which cards are best amongs 6 players.
I was wondering if you know of any good resources that would help me write the code for this algorithm.
Thanks
Matthew
If it were me ...
I would perform as much of the processing up front, apart from examining any particular deal. For example, suppose you created a data set with 2.6M rows and 2 columns (hand identifier and rank). The hand identifier would be a 10-character field representing the 5 cards, such as: 0105234252
That would be a combination of cards "01", "05", "23", "42", and "52", with a separate column indicating the rank. Most of the work would be creating such a file, but you wouldn't have to re-create the logic every time you wanted to use the results. Using it could take various forms. You could load it into a format (permanently saved) or load it as a hash table into a DATA step. Then the look-up would be quick, requiring only that you turn the 5 cards of a hand into a matching 10-character string.
Thanks Astounding
What's your opionion on using IML for this job? Rick has mentioned using a pairwise algorithm for comparing hands but I'm not sure how that would work without having a complex algorithm since poker hands don't follow a natural ordering or score - comparing a flush with a straight? I know there is some order but I don''t know how you would see if one hand is better than the other without go through loads of checks. If you are familiar with IML would you propose a logic for achieving this?
Regarding your approach I have two questions:
1. Is my code above on the right track assuming a change to the number system you have outlined. I will still need to do a load of checks to determine rank i.e. check for flush, straight, 4 of a kind etc.
2. Will having a table with 2.6m entries be too slow. Let say I want to run 300 games and each game has 6 players and 50 plays - how long do you think this would take?
Thank you
Matthew
I don't think you want to generate all combinations. Just write a pairwise comparison algorithm: given two five-card hands, write a function returns whether the first hand beats the second. This binary comparison will enable you to determine the winner of any simulated deal.
Hi Rick
Thanks for your advice. Would you know if any good resources on generating a pairwise algorithm in sas. Also, does it work if there are 6 players and you are trying to determine the best hand, second best and so on?
I work with a team of actuaries who currently don't use (and who are unaware of IML) but I think this would be highliy benefiocial as speed is always an issue for us. We would be working with huge data sets. We have all have SAS version 9 licenses - is it excpensive to get IML as an addition?
Thanks
Matthew
Regarding resources: no, I am not familiar with an existing program that evaluates poker hands.
Regarding "does it work if there are 6 players": yes. Pairwise comparison is the basis for sorting algorithms. If you want to put six words in alphabetical order, you carry out pairwise comparisons in order to rank the words relative to one another.
Thanks Rick,
Well if you knew of resources thgat covered pairwise comparisons in sas that would be a good start - do you cover these in your books?
Thanks
And this model will not model actual playing as very few hands of holdem have all of the players seeing all of the cards. Many drop out before seeing any of the common cards.
Well, I came from non-western culture where Poker has different rules. Since it took me some effort to know Poker rules using Wiki, I will probably use it as the material for a paper for next year SESUG. All of the business requirements are obtained from Wikipedia: List of poker hands - Wikipedia, the free encyclopedia
/*I use 14 to address 'A' for the simplicity of coding. There are 2,598,960 distinct hands,
out of which, there are 7,462 distinct scores, The whole process runs less than 10 secs on my
4x core pc, win7, if you already have the hands, to rank 100 of them takes less than 1 sec*/
/*TO GENERATE 52 CARDS POOL*/
DATA CAT;
INPUT SUIT :$1. @@;
CARDS;
S C H D
;
DATA SEQ;
INPUT NUM :$2. @@;
CARDS;
14 13 12 11 10 09 08 07 06 05 04 03 02
;
PROC SQL NOPRINT;
SELECT DISTINCT QUOTE(CATS(SUIT,NUM)) INTO :HANDS SEPARATED BY ' ' FROM CAT, SEQ;
QUIT;
/*EMBED RANKING ALGORITHM INTO THE FOLLOWING MACRO*/
%MACRO SIM;
DO Z=1 TO 5;
FST(Z)=FIRST(C(Z));
NUM(Z)=INPUT(COMPRESS(C(Z),,'KD'),2.);
END;
CALL SORTC (OF FST(*));
CALL SORTN (OF NUM(*));
/*STRAIGHT FLUSH*/
IF FST(1)=FST(5) AND NUM(5)-NUM(4)=1 AND NUM(4)-NUM(3)=1 AND NUM(3)-NUM(2)=1 AND NUM(2)-NUM(1)=1 THEN
DO;
RANK1=9;
RANK2=NUM(5);
RANK3=999;
RANK4=999;
RANK5=999;
RANK6=999;
END;
ELSE IF FST(1)=FST(5) AND NUM(1)=2 AND NUM(2)=3 AND NUM(3)=4 AND NUM(4)=5 AND NUM(5)=14 THEN DO;
RANK1=9;
RANK2=NUM(4);
RANK3=999;
RANK4=999;
RANK5=999;
RANK6=999;
END;
/*FOUR OF A KIND*/
ELSE IF NUM(1)=NUM(4) OR NUM(2)=NUM(5) THEN
DO;
RANK1=8;
IF NUM(1)=NUM(4) THEN
DO;
RANK2=NUM(1);
RANK3=NUM(5);
RANK4=999;
RANK5=999;
RANK6=999;
END;
ELSE IF NUM(2)=NUM(5) THEN
DO;
RANK2=NUM(2);
RANK3=NUM(1);
RANK4=999;
RANK5=999;
RANK6=999;
END;
END;
/*FULL HOUSE*/
ELSE IF (NUM(1)=NUM(2) AND NUM(3)=NUM(5)) OR (NUM(1)=NUM(3) AND NUM(4)=NUM(5)) THEN
DO;
RANK1=7;
IF (NUM(1)=NUM(2) AND NUM(3)=NUM(5)) THEN
DO;
RANK2=NUM(3);
RANK3=NUM(1);
RANK4=999;
RANK5=999;
RANK6=999;
END;
ELSE IF (NUM(1)=NUM(3) AND NUM(4)=NUM(5)) THEN
DO;
RANK2=NUM(1);
RANK3=NUM(4);
RANK4=999;
RANK5=999;
RANK6=999;
END;
END;
/*FLUSH*/
ELSE IF FST(1)=FST(5) THEN
DO;
RANK1=6;
RANK2=NUM(5);
RANK3=NUM(4);
RANK4=NUM(3);
RANK5=NUM(2);
RANK6=NUM(1);
END;
/*STRAIGHT*/
ELSE IF NUM(5)-NUM(4)=1 AND NUM(4)-NUM(3)=1 AND NUM(3)-NUM(2)=1 AND NUM(2)-NUM(1)=1 THEN
DO;
RANK1=5;
RANK2=NUM(5);
RANK3=999;
RANK4=999;
RANK5=999;
RANK6=999;
END;
ELSE IF NUM(1)=2 AND NUM(2)=3 AND NUM(3)=4 AND NUM(4)=5 AND NUM(5)=14 THEN
DO;
RANK1=5;
RANK2=NUM(4);
RANK3=999;
RANK4=999;
RANK5=999;
RANK6=999;
END;
/*THREE OF A KIND*/
ELSE IF (NUM(1)=NUM(3) OR NUM(2)=NUM(4) OR NUM(3)=NUM(5)) THEN
DO;
RANK1=4;
IF NUM(1)=NUM(3) THEN
DO;
RANK2=NUM(1);
RANK3=NUM(5);
RANK4=NUM(4);
RANK5=999;
RANK6=999;
END;
IF NUM(2)=NUM(4) THEN
DO;
RANK2=NUM(2);
RANK3=NUM(5);
RANK4=NUM(1);
RANK5=999;
RANK6=999;
END;
IF NUM(3)=NUM(5) THEN
DO;
RANK2=NUM(3);
RANK3=NUM(2);
RANK4=NUM(1);
RANK5=999;
RANK6=999;
END;
END;
/*TWO PAIR*/
ELSE IF (NUM(1)=NUM(2) AND NUM(3)=NUM(4)) OR (NUM(1)=NUM(2) AND NUM(4)=NUM(5)) OR (NUM(2)=NUM(3) AND NUM(4)=NUM(5)) THEN
DO;
RANK1=3;
IF (NUM(1)=NUM(2) AND NUM(3)=NUM(4)) THEN
DO;
RANK2=NUM(3);
RANK3=NUM(1);
RANK4=NUM(5);
RANK5=999;
RANK6=999;
END;
IF (NUM(1)=NUM(2) AND NUM(4)=NUM(5)) THEN
DO;
RANK2=NUM(5);
RANK3=NUM(1);
RANK4=NUM(3);
RANK5=999;
RANK6=999;
END;
IF (NUM(3)=NUM(2) AND NUM(5)=NUM(4)) THEN
DO;
RANK2=NUM(5);
RANK3=NUM(3);
RANK4=NUM(1);
RANK5=999;
RANK6=999;
END;
END;
/*ONE PAIR*/
ELSE IF NUM(1)=NUM(2) OR NUM(2)=NUM(3) OR NUM(3)=NUM(4) OR NUM(4)=NUM(5) THEN
DO;
RANK1=2;
IF NUM(1)=NUM(2) THEN
DO;
RANK2=NUM(1);
RANK3=NUM(5);
RANK4=NUM(4);
RANK5=NUM(3);
RANK6=999;
END;
IF NUM(2)=NUM(3) THEN
DO;
RANK2=NUM(3);
RANK3=NUM(5);
RANK4=NUM(4);
RANK5=NUM(1);
RANK6=999;
END;
IF NUM(3)=NUM(4) THEN
DO;
RANK2=NUM(4);
RANK3=NUM(5);
RANK4=NUM(2);
RANK5=NUM(1);
RANK6=999;
END;
IF NUM(4)=NUM(5) THEN
DO;
RANK2=NUM(5);
RANK3=NUM(3);
RANK4=NUM(2);
RANK5=NUM(1);
RANK6=999;
END;
END;
/*HIGH CARD*/
ELSE
DO;
RANK1=1;
RANK2=NUM(5);
RANK3=NUM(4);
RANK4=NUM(3);
RANK5=NUM(2);
RANK6=NUM(1);
END;
%MEND;
/*SCORE ALL OF THE COMBINATIONS*/
data HANDS;
array c[5] $3;
array x[52] $3 (&HANDS.);
array i[5];
ARRAY NUM(5) num1-num5;
ARRAY FST(5) $ 1 fst1-fst5;
n=dim(x);
k=dim(i);
i[1]=0;
ncomb=comb(n,k);
do j=1 to ncomb;
call allcombi(n, k, of i
do h=1 to k;
c
end;
%SIM
OUTPUT;
end;
KEEP C: RANK: num:;
run;
/*ORDER AND RANK DISTINCT SCORES*/
PROC SORT DATA=HANDS OUT=HAND_SORT;
BY DESCENDING RANK1 DESCENDING RANK2 DESCENDING RANK3 DESCENDING RANK4 DESCENDING RANK5 DESCENDING RANK6;
RUN;
DATA RANKS (KEEP=RANK: ORDER);
SET HAND_SORT;
BY DESCENDING RANK1 DESCENDING RANK2 DESCENDING RANK3 DESCENDING RANK4 DESCENDING RANK5 DESCENDING RANK6;
IF FIRST.RANK6;
ORDER+1;
RUN;
/*RANDOM SAMPLE: CAN ALSO BE DONE USING DATA STEP*/
PROC SURVEYSELECT DATA=WORK.HANDS
OUT=WORK.SAMPLE (KEEP=C:)
METHOD=SRS
N=90000;
RUN;
/*RANK THE SAMPLE DATA, THERE ARE MANY WAYS FOR THIS KIND OF LOOK UP, HERE IS TO USE HASH() TABLE*/
DATA WANT;
IF _N_=1 THEN
DO;
IF 0 THEN
SET RANKS;
DECLARE HASH H(DATASET:'RANKS');
H.DEFINEKEY('RANK1', 'RANK2','RANK3','RANK4', 'RANK5','RANK6');
H.DEFINEDATA(ALL:'Y');
H.DEFINEDONE();
END;
SET SAMPLE;
array c[5] $3;
ARRAY NUM(5) num1-num5;
ARRAY FST(5) $ 1 fst1-fst5;
%SIM
RC=H.FIND();
KEEP C: ORDER;
run;
Update:
Got a PM saying that since I use '14' for ACE that I miscategorized 'Steel Wheel' and 'Wheel' (Meaning A-2-3-4-5 is still qualified for 'Straight') , hence the update.
Update 2:
FYI: Given OP has 300 games, 6 players and each for 50 plays, that counts for 90,000 hand. To rank them took less than 1 sec on my machine. It is really not a heavy-duty computing job by any means.
Hi Hai.kuo
Thanks for your help. In your update, have you changed your code so no a steal weel still qualifies for a straight?
Re the speed, that's great. I really appreciate your help - i wouldn't have been able to come up with something like that myself.
I have drafted up an email and I was going to PM you. Would that be ok? I've just outlined the background of what I'm trying to do.
Thanks
Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.
If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website.
Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.
Find more tutorials on the SAS Users YouTube channel.