Help using Base SAS procedures

Generate Poker Hands in SAS

Accepted Solution Solved
Reply
Regular Contributor
Posts: 202
Accepted Solution

Generate Poker Hands in SAS

Hi

I'm trying to build a program that generates poker game results based on predetermined assumptions about the players. I'm trying to come up with a simple enough algorithm that ranks the hands of players and allocates chips to the best hand. In Texas Holdem there are 2,598,960 unique poker hands but this can be reduced to 7462 distinct poker hand values.

A couple of initial questions. The program will allocate two distinct poker cards from a deck - i've coded them such that 13H is the Ace of Hearts for example. I was going to have a table with the 52 card values and have the cards generated based on the rand function that picks a value between 1 and 52, however, it just occurred to me that when the program allocated a hand to the next player it can't repeat either of the cards allocated to the previous player. The data set I'm thinking will look someting like this:

Player 1Player 2Player 3Player 4Player 5Player 6Shared Card 1Shared Card 2Shared Card 3
13H02C09S07S12D02D06H03D01D
..................

Once the cards are allocated (so all cards are unique as mentioned above), the algorithm then needs to lookup a table so each player is given a value between 1 and 7462 and the chips are allocated based on the highest hand value.

I need to be able to run this algorithm 1000s of times so I can derive a distribution of profit based on the assumptions entered into the alogorithm so speed is important. I've spent a couple of hours on this so far and I'm having some trouble getting started as I'm not sure of a function that restricts the random function from repeating the same value and I'm also concerned that If I have a table that has every possible poker hand that the program will perform very slowly.

Any help would be much appreciated.

Regards

Matthew


Accepted Solutions
Solution
‎06-19-2014 02:23 PM
SAS Employee
Posts: 16

Re: Generate Poker Hands in SAS

I have great news for you. The SAS University Edition includes SAS/IML and is free!

Free Statistical Software, SAS University Edition | SAS

The SAS University Edition is for personal use, but it is not limited to academia. That is, you don't have to be an enrolled student to access it. Note that this is intended for learning purposes only, so don't use it for paid work. Enjoy!

Best,

Steve

View solution in original post


All Replies
Esteemed Advisor
Posts: 7,269

Re: Generate Poker Hands in SAS

Something like this perhaps? This generates a number of data sets specified by the parameter Runs, for given number of Players which better be less than 25. The sets are named sequentially as hand1, hand2 etc. with a player identifier, his two dealt cards as card1 and card2 and 4 common cards named common1 through 4.

%macro holdem(Runs=,players=);
%do i = 1 %to &runs;
data cards;
length rank $ 2 suit $1 card $ 3;;
do rank='A','1','2','3','4','5','6','7','8','9','10','J','Q','K';
  do suit = 'C','D','H','S';
   card= cats(rank,suit);
   rand= ranuni(546);
  output;
end;
end;
drop rank suit;
run;
proc sort data=cards; by rand;run;
%let p = &players;/* number of players*/
data deal;
     set cards;  /*after resort on the random value*/
     retain counter ;
     counter +1;
     player = mod(counter,&p)+1;
     if counter gt (&p*2) then do;
   common= 1;/* the common cards*/
   player = .;
  end;
     if counter gt (&p*2 + 4) then stop;
run;
proc sort data=deal; by player;run;
proc transpose data=deal(where=(player ne .)) prefix=card
     out=players;
by player;
var card;
run;

proc transpose data=deal(where=(player = .)) prefix=common
     out=common;
by player;
var card;
run;

proc sql;
create table hand&i as
select a.player, a.card1, a.card2, b.common1,b.common2,b.common3,b.common4
from players as a , common as b
;
quit;

%end;
%mend;

%holdem(Runs=3,players=4);

Its up to you to combine/rank the card combinations and assign your values. Options would be to include the run counter in the hand set, add ",&i as RunCounter" after the b.common4 in the last step.

If you want all of the datasets combined
data allhand;

     set hand: ;

run;

should do it.

Regular Contributor
Posts: 243

Re: Generate Poker Hands in SAS

Hi,

do rank='A','1','2','3','4','5','6','7','8','9','10','J','Q','K';


in this you are creating 56 cards,

i guess it should like : do rank='A','2','3','4','5','6','7','8','9','10','J','Q','K';



Regular Contributor
Posts: 202

Re: Generate Poker Hands in SAS

Hi Ballardw

Thank you very much for your detailed and helpful reply. I've worked through the code and I now understand the logic. The only puzzling thing is that when I execute the macro, my hand1, 2 and 3 are the same. I went through each step and the first data step doesn't seem to generate a different random set of numbers each time the macro loops. I keep getting .98956 as the first entry in the column rand. Do you know what might be causing this?

Kind Regards

Matthew

Regular Contributor
Posts: 202

Re: Generate Poker Hands in SAS

Hi Ballardw

Just following up on my message above re the ranuni function - would you have an idea of why this is happening?

Thanks

Matthew

Esteemed Advisor
Posts: 7,269

Re: Generate Poker Hands in SAS

The repeated runs are likely the fixed seed in the random generator. It's a feature that allows duplication of random sequences and I used that for debugging. So leave the parantheses emtpy in the ranuni call.

Sorry about the A 1 confusion.

Regular Contributor
Posts: 202

Re: Generate Poker Hands in SAS

Hi ballardw

I tried putting it in ranuni() instead of ranuni(546) and I got an error message saying "The Ranuni function Call does not have enopugh arguments"...

SAS Employee
Posts: 16

Re: Generate Poker Hands in SAS

Hi brophymj,

You can't call ranuni without arguments. Instead, use ranuni(0).

Best,

Steve

Esteemed Advisor
Posts: 7,269

Re: Generate Poker Hands in SAS

use &i in the ranuni. That will generate a different stream for each run.

SAS Employee
Posts: 16

Re: Generate Poker Hands in SAS

Matthew,

Given that you want to run the simulation for 1000's of hands, you should consider running the simulation in IML. Using macros to run the simulation using data steps may be time consuming. For example, I ran the above code for 10,000 runs with 9 players. The simulation took 9:56. In contrast, running the simulation under the same conditions in IML with the code shown below took under a second.

Best,

Steve

proc iml;

  nruns = 10000; *Specify number of runs;

  nplayers = 9; *Specify number of players;

  rank = {A,1,2,3,4,5,6,7,8,9,10,J,Q,K};

  suit = {C,D,H,S};

  do i = 1 to 4;

    do j = 1 to 14;

      deck = deck // concat(strip(rank),suit);

    end;

  end;

  free rank suit;

  hands = J(nruns,nplayers+5,'                      ');

 

  do i = 1 to nplayers;

    name = name || ({player}+strip(char(i)));

  end;

  name = name || {community1 community2 community3 community4 community5};

  mattrib hands colname=name;

  do run = 1 to nruns;

    order = j(52,1,0);

    call randgen(order,'uniform');

    call sortndx(index,order);

    deck_shuffled = deck[index];

    card=1;

    do player = 1 to nplayers;

      hands[run,player] = concat(deck_shuffled[card,],{", "},deck_shuffled[card+1,]);

      card=card+2; 

    end;

    hands[run,nplayers+1:nplayers+5] = deck_shuffled[card:card+4]`;

  end;

  create hands from hands [colname=name];

  append from hands;

  close hands;

quit;

Post a Question
Discussion Stats
  • 15 replies
  • 1759 views
  • 4 likes
  • 6 in conversation