# Which is better probability-wise two pair or pocket pair two pairs

In Texas holdem on the flop is it better for someone to have two pairs where the pair is a pocket pair combined with a pair on the flop, or is it better to have a two pair where the two hole cards match with two cards on the flop? I mean specifically, what are the chances of him being beaten by another player making a two pair or the probability of him making another two pair based on how the board is.

So I'm comparing for example this:

Hole cards: TsTc
Flop cards: 5c5hKd
Hand: TsTc5c5h - two pair


With this:

Hole cards: Ts5c
Flop cards: Tc5hKd
Hand: TsTc5c5h - two pair


I could ask on the poker stackexchange but I figured you mathematicians would come up with a more accurate answer. If my question is not clear, please let me know so I can edit it.

Given your hole cards and the flop, there are $$\binom{47}{2,2,43} = \frac{47!}{2!\; 2! \; 43!} = 1,070,190$$ possible continuations of the game with two more community cards and two cards for your opponent's hole cards. By exhaustive enumeration, also known as brute force, the number of continuations in which you win in the first scenario is $$771,110$$ and the number in the second scenario is $$935,385$$. (I used a Python program.)

So your probability of winning in the first scenario is $$771,110 / 1,070,190 = 0.729536$$ and in the second scenario is $$935,385 / 1,070,190 = 0.874036$$.

EDIT

By request, here is the Python program used in the solution. Most of the code was copied from an example presented in a Udacity course, CS212, "Design of Computer Programs" taught by Peter Norvig. The heart of the CS212 code is the function hand_rank, which returns an object representing the rank of a five card poker hand. The representation of the rank is elegant and ingenious: an integer representing the class of hand (one pair, flush, etc.) followed by a list which serves to rank hands of the same class. The code runs under Python 2.7.

# Compare two scenarios in Texas hold-em by brute-force enumeration.

import itertools

def wins(hole, flop):
"""Try all possible outcomes of hold-em with given hole and flop cards,
return number of wins."""
# First construct the complete 52-card deck.
deck = [r+s for r in '23456789TJQKA' for s in 'SHDC']
# Remove the given hole and flop cards from the deck.
for x in hole+flop:
deck.remove(x)
nwins = 0
# Itertools does not provide a convenient method to extract two sets
# of two cards each from the deck.  So we draw four cards and break
# the four cards into two sets of two, which can be done in six ways.
for (a,b,c,d) in itertools.combinations(deck, 4):
for (x,y) in [[[a,b],[c,d]],
[[a,c],[b,d]],
[[a,d],[b,c]],
[[b,c],[a,d]],
[[b,d],[a,c]],
[[c,d],[a,b]]]:
common = flop + x  # 5 common cards
ophole = y         # opponent's hole cards
mybest = best_hand(common + hole)
opbest = best_hand(common + ophole)
if hand_rank(mybest) > hand_rank(opbest):
nwins += 1
return nwins

# Code from Udacity CS212, "Design of Computer Programs", starts here

def best_hand(hand):
"From a 7-card hand, return the best 5 card hand."
return max(itertools.combinations(hand,5), key=hand_rank)

def hand_rank(hand):
"Return a value indicating the ranking of a hand."
ranks = card_ranks(hand)
if straight(ranks) and flush(hand):
return (8, max(ranks))
elif kind(4, ranks):
return (7, kind(4, ranks), kind(1, ranks))
elif kind(3, ranks) and kind(2, ranks):
return (6, kind(3, ranks), kind(2, ranks))
elif flush(hand):
return (5, ranks)
elif straight(ranks):
return (4, max(ranks))
elif kind(3, ranks):
return (3, kind(3, ranks), ranks)
elif two_pair(ranks):
return (2, two_pair(ranks), ranks)
elif kind(2, ranks):
return (1, kind(2, ranks), ranks)
else:
return (0, ranks)

def card_ranks(hand):
"Return a list of the ranks, sorted with higher first."
ranks = ['--23456789TJQKA'.index(r) for r, s in hand]
ranks.sort(reverse = True)
return [5, 4, 3, 2, 1] if (ranks == [14, 5, 4, 3, 2]) else ranks

def flush(hand):
"Return True if all the cards have the same suit."
suits = [s for r,s in hand]
return len(set(suits)) == 1

def straight(ranks):
"""Return True if the ordered
ranks form a 5-card straight."""
return (max(ranks)-min(ranks) == 4) and len(set(ranks)) == 5

def kind(n, ranks):
"""Return the first rank that this hand has
exactly n-of-a-kind of. Return None if there
is no n-of-a-kind in the hand."""
for r in ranks:
if ranks.count(r) == n: return r
return None

def two_pair(ranks):
"""If there are two pair here, return the two
ranks of the two pairs, else None."""
pair = kind(2, ranks)
lowpair = kind(2, list(reversed(ranks)))
if pair and lowpair != pair:
return (pair, lowpair)
else:
return None

# End of code from CS212

print wins('TS TC'.split(), '5C 5H KD'.split()) # scenario 1
print wins('TS 5C'.split(), 'TC 5H KD'.split()) # scenario 2

• Is that vs one other opponent? Also is that your own python program or otherwise? I'd be interested to see the program if possible. – Hasen Mar 22 at 7:28
• @Hasen Yes, that is versus one other opponent. If I were to add more opponents I think exhaustive enumeration would not be feasible on my slow old PC. You might then switch to Monte Carlo methods. Most of the code (the hard part, ranking poker hands) was copied from an example given in the Udacity course "Design of Computer Programs" taught by Peter Norvig. Give me some time to clean up the code a bit and I'll post it. – awkward Mar 22 at 12:21
• @Hasen The code is now added. – awkward Mar 22 at 14:07
• Wow that's awesome, you even posted the code too. I'll take a look at it. – Hasen Mar 24 at 16:36
• Btw is this code tested and working for you? I've never used python before, I normally use php and some others but I set up python 3 to try this code and for some reason it's showing an unknown syntax error with the final two print wins lines? Print is underlined in linter but the error is just "unknown"...not too helpful for an error message. – Hasen Mar 24 at 19:33