Frequency of certain poker hands simulation

Page 1 of 1

3 Replies - 5733 Views - Last Post: 04 March 2011 - 11:41 AMRate Topic: //<![CDATA[ rating = new ipb.rating( 'topic_rate_', { url: 'https://www.dreamincode.net/forums/index.php?app=forums&module=ajax&section=topics&do=rateTopic&t=220167&amp;s=d342c6f41f41f4c4c149dde3b3cacf2f&md5check=' + ipb.vars['secure_hash'], cur_rating: 0, rated: 0, allow_rate: 0, multi_rate: 1, show_rate_text: true } ); //]]>

#1 cuddledumpling

• New D.I.C Head

Reputation: 0
• Posts: 3
• Joined: 04-March 11

Frequency of certain poker hands simulation

Posted 04 March 2011 - 06:55 AM

I need help in writing a program to simulate the shuffling and dealing of a large number of hands (i.e: 100,000) and to report the frequency of the hands.

I am interested in the frequency of 10 hands:
Royal Flush (10, Jack, Queen, King, Ace, all of the same suit)
Straight Flush (ﬁve ranks in a row, all of the same suit)
Four of a Kind (four cards of the same rank)
Full House (three of one rank and two of another)
Flush (ﬁve cards of the same suit); Straight (ﬁve ranks in a row)
Three of a Kind (three of one rank, but not a full house or four of a kind)
Two Pair (two each of two di"erent ranks)
Pair (two of the same rank, but not Two Pair, three or four of a kind)
High Card (if none of the previous categories ﬁt)

I don't quite know how to start the program but this is what I have so far:

```import time
import random

flush=0
royal=0
n=int(input("number of hand="))
t1=time.clock()
for i in range(n):
count1=count2=count3=count4=0
for i in range(0,5):
card=random.choice(['a',2,3,4,5,6,7,8,9,10,'j','q','k'])
suit=random.choice(['s','d','h','c'])
if suit=='s':
count1+=1
elif suit=='d':
count2+=1
elif suit=='h':
count3+=1
else:
count4+=1
if count1==5 or count2==5 or count3==5 or count4==5:
flush=flush+1
count5=count6=count7=count8=0
card1=random.choice([10,'j','q','k','a'])
if suit=='s':
count5+=1
elif suit=='d':
count6+=1
elif suit=='h':
count7+=1
else:
count8+=1
if count5==5 or count6==5 or count7==5 or count8==5:
royal=royal+1

print("number of flushes",flush)
prob=float(flush)/float(n)
print("prob of flush",prob)

print("number of royal flushes",royal)
prob1=float(royal)/float(n)
print("prob of royal flush",prob1)

t2=time.clock()
process=round(t2-t1,2)
print("prossess time",process,"sec")

```

It prints out something like this:
number of hand=100000
number of flushes 365
prob of flush 0.00365
number of royal flushes 0
prob of royal flush 0.0
prossess time 4.62 sec

I'm pretty sure there is a more effective way to figure out the probabilities of those ten hands. Please help.

Thanks.

Is This A Good Question/Topic? 0

Replies To: Frequency of certain poker hands simulation

#2 atraub

• Pythoneer

Reputation: 828
• Posts: 2,236
• Joined: 23-December 08

Re: Frequency of certain poker hands simulation

Posted 04 March 2011 - 08:09 AM

I'd suggest an overhaul to your design. First off, there's nothing preventing your program from creating 2 identical cards. You could put in a check to make sure that every card is unique, or you could just make a real deck. I prefer the latter.

```def makeDeck():
#jack is 11, queen is 12, king is 13, Ace is 14
deck = []
for suit in 'sdhc':
for value in range(2,15):
deck.append(suit+str(value))
return deck

```

That's a nice deck. The benefit to this deck function is that it can be reused in other applications.

now to deal a hand. Well, that's easy, let's just grab the first 5 cards:
hand = deck[:5]
To make it easier to determine a royal flush, let's sort our hand
hand.sort()

Now, let's create a function to tell us if this hand is a royal straight flush:
```def isRoyalFlush(hand):
suit = hand[0][0]
return hand == [suit+'10', suit+'11', suit+'12', suit+'13', suit+'14']
```

If it's a royal flush, it'll return true. Otherwise, it returns false. Your program will be a lot cleaner using this style.

```from random import shuffle

def main(n = -1):
if n == -1:#Let's you say main(5000) to run it 5000 times, but also let's the user dictate it while running
n=int(input("number of hands: "))
royalFlushes = 0
deck = makeDeck()

for i in range(n):
shuffle(deck)
hand = getHand(deck)
if isRoyalFlush(hand):
royalFlushes+=1
print("Number of royal flushes: "+str(royalFlushes))

def makeDeck():
#jack is 11, queen is 12, king is 13, Ace is 14
suits = 'sdhc'
deck = []
for suit in suits:
for value in range(2,15):
deck.append(suit+str(value))
return deck

def getHand(deck, size=5):
hand = deck[:size]
hand.sort()
return hand

def isRoyalFlush(hand):
suit = hand[0][0] #get the first card, then get that card's suit
return hand == [suit+'10', suit+'11', suit+'12', suit+'13', suit+'14']

```

Clearly, you want your program to do more. This should give you a good foundation to work from though. All you need to do is create a function for each type of hand you want to detect and implement a time keeping mechanism. What do you think?

NOTES:
• for a given card, the suit is: card[0]
• for a given card, the value is: card[1:] This accounts for values that are two digits.
• A hand is a subset of the deck, thus hands do not remove cards from the deck. This allows us to keep the same deck object for each run. We simply have to shuffle it between each test.

This post has been edited by atraub: 04 March 2011 - 07:01 PM
Reason for edit:: Updated the crap out of it!

#3 cuddledumpling

• New D.I.C Head

Reputation: 0
• Posts: 3
• Joined: 04-March 11

Re: Frequency of certain poker hands simulation

Posted 04 March 2011 - 11:32 AM

I tried to do things like this. The stuff I put in comments are because I can't really figure out how to write the code for the hands.

```#from random import shuffle
import time
from random import randrange

start = time.clock() #starts clock

def main():
n = int(input("number of hands: "))
royalFlushes = 0
##   straightFlushes = 0
##   fourOfaKind = 0
##   fullHouse=0
##   flush = 0
##   straight = 0
##   threeOfaKind = 0
##   twoPair = 0
##   pairCard = 0
##   highCard = 0
deck = makeDeck()
for i in range(n):
#shuffle(deck)
hand = getHand(deck)
#print(hand)
if isRoyalFlush(hand):
##         royalFlushes+=1
##      if isStraightFlush(hand):
##         straightFlushes+=1
##      if isFourofakind(hand):
##         fourOfaKind+=1
##      if isFullHouse(hand):
##         fullHouse+=1
##      if isFlush(hand):
##         flush+=1
##      if isStraight(hand):
##         straight+=1
##      if isThreeofakind(hand):
##         threeOfaKind+=1
##      if isTwopair(hand):
##         twoPair+=1
##      if isPaircard(hand):
##         pairCard+=1
##      if isHighcard(hand):
##         highCard+=1
print("Number of royal flushes: "+str(royalFlushes))
probroyal=int(royalFlushes)/n
print("Probability of a royal flush:",probroyal)

def makeDeck():
#jack is 11, queen is 12, king is 13, Ace is 14
suits = 'sdhc'
deck = []
for suit in suits:
for value in range(2,15):
deck.append(suit+str(value))
return deck

def getHand(deck):
hand = []
check = 53
for i in range(0,5):
while True:
pos =randrange(0,52)
if pos != check:
break
hand.append(deck[pos])
check = pos
hand.sort()
return hand

def isRoyalFlush(hand):
if hand[0][0] == hand[1][0] == hand[2][0] == hand[3][0] == hand[4][0]:
string = ''
for x in hand:
n = len(x)
string = string + x[1:n]
print(string)
if string == '1011121314':
return True
else:
return False
##   suit = hand[0][0] #get the first string, then get the first letter of that string
##   return hand == [suit+'10', suit+'11', suit+'12', suit+'13', suit+'14']

#def isStraightFlush(hand):
# if

#def isFourofakind(hand):

#def isFullHouse(hand):

#def isFlush(hand):

#def isStraight(hand):

#def isThreeofakind(hand):

#def isTwopair(hand):

#def isPaircard(hand):

#def isHighcard(hand):

#main()

end = time.clock() #stops clock
process = round(end - start)
print("process time:",process,"seconds")

```

#4 atraub

• Pythoneer

Reputation: 828
• Posts: 2,236
• Joined: 23-December 08

Re: Frequency of certain poker hands simulation

Posted 04 March 2011 - 11:41 AM

I'm having trouble figuring out what you gain from
```def getHand(deck):
hand = []
check = 53
for i in range(0,5):
while True:
pos =randrange(0,52)
if pos != check:
break
hand.append(deck[pos])
check = pos
hand.sort()
return hand
```
as oppose to:
```def getHand(deck, size=5):
hand = deck[:size]
hand.sort()
return hand

```

If your deck is already shuffled, then you don't need to bother with the nonsense of trying to randomly pick cards out of it. I don't know about you, but I shuffle then deal from the top.

The same can be said for the way you get royal flushes. Look at the simple algorithm I gave you:
Check the suit of the first card. Assuming the cards are sorted, see if the cards are a 10,jack,queen,king,ace of that suit, if they are, you have a royal flush.
```def isRoyalFlush(hand):
suit = hand[0][0] #get the first card, then get that card's suit
return hand == [suit+'10', suit+'11', suit+'12', suit+'13', suit+'14']
```
If you want to make it easier to read, you could say
```def isRoyalFlush(hand):
suit = hand[0][0] #get the first card, then get that card's suit
if hand == [suit+'10', suit+'11', suit+'12', suit+'13', suit+'14']:
return True
else:
return False
```

The functionality of those two code blocks is identical. I just prefer the former style because it has 1 exit point and it essentially says "return the output of checking for this condition".

I don't understand why you're rejecting good, simple algorithms for convoluted and unnecessarily complex ones.

This post has been edited by atraub: 08 March 2011 - 09:43 AM