Turn on suggestions

Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- Home
- /
- Programming
- /
- SAS Procedures
- /
- Allocating Values to Poker Hands

Options

- RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

🔒 This topic is **solved** and **locked**.
Need further help from the community? Please
sign in and ask a **new** question.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Posted 06-18-2014 06:09 AM
(3416 views)

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

1 ACCEPTED SOLUTION

Accepted Solutions

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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.

20 REPLIES 20

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

Maybe you should check call greycode() routine.But I don't know if it could handle 26 cards ,check documentation.

Xia Keshan

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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;

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.

- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content

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. **

What is Bayesian Analysis?

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.