Solved – Count Outcomes in Three Card Poker

gamesprobability

I'm currently trying to verify the probabilities and outcomes for three card poker. The game is essentially the same as 5 card poker, but with three cards. The game is played against the dealer.

If we assume one standard deck, I can get the probabilities for each outcome of dealing three cards. (See bottom of post for explanation of a standard deck and 3-card poker hands).


  • Total Possible Outcomes:
    $$C(52,3)=22,100$$
  • Straight Flush: (# of suits) * (# of start ranks)
    $$4*12=48$$
  • Three of a Kind: (Choose a rank) * (Choose three suits)
    $$C(13,1)*C(4,3)=52$$
  • Straight: (Choose a starting rank) * (Choose Three Suits) – (# Straight Flushes)
    $$C(12,1)*C(4,1)^{3}-48=720$$
  • Flush: (Choose a suit) * (Choose 3 ranks) – (# Straight Flushes)
    $$C(4,1) * C(13,3) – 48 = 1,096$$
  • Pair: (Choose a rank) * (Choose 2 suits) * (Choose a 3rd card)
    $$C(13,1)*C(4,2)*48=3,744$$
  • Ace High or less:
    $$22,100-\sum(3,744+1,096+720+52+48)=16,440$$

Admittedly, I took the lazy way out on the last one. I just found out that these counts and probabilities are on the "Wizard of Odds" site:
http://wizardofodds.com/games/three-card-poker/

This is great, and my counts are verified.


But, I also want to count the total possible outcomes when considering a player AND the dealer.

Where:

  • Total Possible Outcomes: (# of ways to get 6 from 52) * (# of ways to get 3 player cards from 6)
    $$C(52,6)*C(6,3)=407,170,400$$

Here is where I start to run into problems. The wizard of odds site has the outcomes broken out as follows:

  Hand                  Outcome              Count
---------------------------------------------------------
| Straight Flush      | Player Wins        | 617,044    |
---------------------------------------------------------
| Straight Flush      | Player Ties        | 144        |
---------------------------------------------------------
| Straight Flush      | Player Loses       | 968        |
---------------------------------------------------------
| Straight Flush      | Dealer Not Qualify | 266,196    |
---------------------------------------------------------
| Three of a Kind     | Player Wins        | 665,776    |
---------------------------------------------------------
| Three of a Kind     | Player Ties        | 0*         |
---------------------------------------------------------
| Three of a Kind     | Player Loses       | 3,312      |
---------------------------------------------------------
| Three of a Kind     | Dealer Not Qualify | 288,960    |
---------------------------------------------------------
...

*Note: Obviously with only one deck, you cannot tie with the dealer on a three of a kind.

I'm mostly drawing a blank here. How are these calculated. I think I can do the easiest one though. 144 possible ties with a straight flush. This is just:

  • Tie with a Straight Flush: (# of ways to get a straight flush) * (# of suits left (3))
    $$48*3=144$$
  • Player Loses with a Straight Flush: Here's my attempt. In order to lose while having a straight flush, the dealer must get a straight flush with a higher starting rank. So if you are dealt a A-2-3, the dealer must have a straight flush that starts with a 2 or higher. There are 4*11=44 ways a dealer can have that. Since there are 4 ways you can get the A-2-3, the total ways you can lose would be 4*4*11 = 176. If we extend this for all possible straight flushes:
    $$4*4*(11+10+9+8+7+6+5+4+3+2+1+0)=1,056\neq968$$
    EDIT (Thanks for @soakley for pointing this out)
    For the above, I'm over counting the situation where the dealers flush overlaps with the player's suit. When the straight flush overlaps, the dealer only has three suits to choose from. Since that can only happen twice, we reduce the count by 2 and add 3*2=6 to each sum. Making the calculation slightly more complicated:
    $$2+4\sum_{i=0}^{9}(4i + 6)=4*((4*9+6)+(4*8+6)+(4*7+6)+(4*6+6)+(4*5+6)+(4*4+6)+(4*3+6)+(4*2+6)+(4*1+6)+(4*0+6)+2) = 968$$

The (4*0+6) term is when the player has a 10-J-Q hand, and the dealer can only win by having 3 suits for J-Q-K and 3 suits for Q-K-A = 6 choices.

  • Player Wins with a Straight Flush: Ok last question, I won't keep updating this with each outcome, I promise.

Here is my strategy for this outcome: 1) The player has a straight flush, and the dealer has less than a straight flush (or = +) 2) the player has a straight flush and the dealer has a lesser straight flush. Any strategy pointers on this would be appreciated.


My final question: Thanks to @soakley, and to writing out larger and larger formulas, I'm getting bogged down. Would the best strategy be to write a program that loops through all hands and counts the outcomes? This isn't for a class, but more for a generic presentation about probabilities for this game. Is a simulation acceptable for such purposes?

Please let me know if I was unclear about anything, or if you need more information. Any pointers would be greatly appreciated.


Edit to include definitions

Standard Deck: Consists of 52 cards. Each Card has a rank and suit. There are 4 suits (Hearts, Diamonds, Clubs, and Spades). There are 13 ranks (in order: A, 2, 3, …, 9, 10, Jack, Queen, King). One small caveat is that Ace can stand for value 1 OR the value above the King (14).

Standard 3 card poker rules: You are to make the best hand out of 3 cards. If two hands are equivalent, the tie is broken by highest rank. It is possible for ties to occur if all the ranks are equivalent.

Possible hand types (in order from lowest worth to highest worth):

"High Card": The hand does not contain any of the below special hands, and is usually said with the highest of the three card ranks. E.g. "10, 6, 4" is called "Ten high" and beats a nine-high hand or lower.

"Pair": Exactly two of the three cards have the same rank without having any of the below hands.

"Flush": All three of the cards have the same suit without having any of the below hands.

"Straight": All three of the cards have consecutive ranks. E.g. "5, 6, 7" or "A, 2, 3" or "Q, K, A". You cannot have a wrap-around straight (i.e., the hand "K-A-2" is not a straight).

"Three of a Kind": All three of the cards have the same rank. E.g. "5, 5, 5".

"Straight Flush": The three cards make a straight and a flush. E.g. "5H, 6H, 7H". It is also worth mentioning the highest hand, called a "Royal Straight Flush" which is a Q, K, A in the same suit (note: there are only 4 possible royal flushes).

Best Answer

Here's a Python program that I believe is correct. It takes a little under 7 minutes on my machine to run through every pair of hands.

from itertools import combinations
from collections import Counter

JACK, QUEEN, KING, ACE = 11, 12, 13, 14

N_HANDS = 22100       # 52 choose 3

deck = frozenset((rank, suit)
  for rank in range(2, ACE + 1)
  for suit in range(4))
assert len(deck) == 52

evaluate_hand_cache = {}
def evaluate_hand(hand):
    if hand not in evaluate_hand_cache:
        evaluate_hand_cache[hand] = evaluate_hand_(hand)
    return evaluate_hand_cache[hand]

def evaluate_hand_(hand):
    ranks = tuple(sorted((rank for (rank, _) in hand), reverse = True))
    suits = [suit for (_, suit) in hand]
    if ranks[0] == ranks[1] == ranks[2]:
      # Three of a kind
        return (5, ranks[0])
    straight = (ranks[0] == ranks[1] + 1 == ranks[2] + 2
        or ranks == (ACE, 3, 2))
    flush = suits[0] == suits[1] == suits[2]
    if straight and flush:
        return (6, ranks[0])
    if straight:
        return (4, ranks[0])
    if flush:
        return (3,) + ranks
    if ranks[0] == ranks[1]:
      # Pair
        return (2, ranks[0], ranks[2])
    if ranks[1] == ranks[2]:
      # Also a pair
        return (2, ranks[2], ranks[0])
    return (1,) + ranks

results = Counter()
divisor = N_HANDS // 100

for i, dealer_hand in enumerate(combinations(deck, 3)):
    if i % divisor == 0:
        print "{}% complete".format(i // divisor)
    dealer_hand = frozenset(dealer_hand)
    dealer_e = evaluate_hand(dealer_hand)
    for player_hand in combinations(deck - dealer_hand, 3):
        player_e = evaluate_hand(player_hand)
        outcome = (
          'Dealer does not qualify'
              if dealer_e < (2, QUEEN) else
          'Player loses'
              if player_e < dealer_e else
          'Player wins'
              if dealer_e < player_e else
          'Tie')
        results[(player_e[0], outcome)] += 1

print "Player hand class,Outcome,Count"
for (hand, outcome), n in sorted(results.items()):
    print ','.join([str(hand), outcome, str(n)])

The output is:

Player hand class,Outcome,Count
1,Dealer does not qualify,264851952
1,Player loses,38038608
2,Dealer does not qualify,60280560
2,Player loses,8453520
2,Player wins,242784
2,Tie,2592
3,Dealer does not qualify,17630040
3,Player loses,1260596
3,Player wins,1298780
3,Tie,3288
4,Dealer does not qualify,11581584
4,Player loses,267804
4,Player wins,1392204
4,Tie,23688
5,Dealer does not qualify,836520
5,Player loses,3312
5,Player wins,118216
6,Dealer does not qualify,771024
6,Player loses,956
6,Player wins,112204
6,Tie,168
Related Question