Compare Complete and Partial Poker Hands
RipplingSoftware Engineer · Technical ScreenLast updated
Implement a poker hand evaluator that determines whether an incomplete poker hand can be completed from the remaining deck to beat an opponent's complete five-card hand.
Problem Statement
You are given two poker hands drawn from a standard 52-card deck without replacement:
complete_hand: A list of exactly 5 cards representing your opponent's revealed hand.partial_hand: A list of 3 or 4 cards representing your incomplete hand.
A card is represented as a two-character string: the first character is the rank ('2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A') and the second character is the suit ('C', 'D', 'H', 'S').
Rank order from lowest to highest: 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A.
Hand categories from lowest to highest:
- High Card: Highest rank card.
- One Pair: Two cards of the same rank.
- Two Pair: Two different pairs.
- Three of a Kind: Three cards of the same rank.
- Straight: Five cards of sequential rank (Ace can be high
T-J-Q-K-Aor lowA-2-3-4-5). - Flush: Five cards of the same suit.
- Full House: Three of a kind and a pair.
- Four of a Kind: Four cards of the same rank.
- Straight Flush: Five cards of sequential rank and the same suit.
When comparing two 5-card hands, compare their category first. If categories match, break ties by comparing key card ranks (e.g., higher pair rank first), followed by kickers in descending order. In this problem, suit does not break ties (equal hands result in a tie).
Return True if there exists at least one combination of cards from the remaining unseen cards in the deck that can complete partial_hand to 5 cards such that it strictly beats complete_hand. Return False otherwise.
Function Signature
def can_beat(complete_hand: list[str], partial_hand: list[str]) -> bool:
pass
Examples
Example 1
complete_hand = ["9C", "9D", "4S", "7H", "2D"] # One Pair of 9s
partial_hand = ["AS", "KS", "QS", "JS"] # 4 cards to a Royal Flush
can_beat(complete_hand, partial_hand) # Returns: True
Explanation: Adding "TS" completes a Straight Flush (Royal Flush), which beats One Pair.
Example 2
complete_hand = ["AS", "AC", "AD", "AH", "KS"] # Four of a Kind (Aces)
partial_hand = ["2C", "3D", "4H", "5S"] # Open-ended straight draw
can_beat(complete_hand, partial_hand) # Returns: False
Explanation: Even if completed into a straight (with a 6 or Ace), the best category achievable cannot beat Four of a Kind.
Constraints
complete_handcontains exactly 5 unique valid cards.partial_handcontains 3 or 4 unique valid cards.- There are no duplicate cards across both hands.
- Cards are drawn from a standard 52-card deck.
Hints
Hint 1
Modularize your code by writing a helper function that maps any 5-card hand into a comparable tuple: `(category_score, tie_breaker_ranks...)`.
Hint 2
Generate the pool of available cards by subtracting cards in both `complete_hand` and `partial_hand` from the full 52-card deck.
Hint 3
Since `partial_hand` has 3 or 4 cards, there are at most 44 choose 2 (946) combinations to check, making a direct search feasible.
Follow-up questions
- How would you optimize the search if the partial hand only contained 1 or 2 cards (up to 160,000+ combinations)?
- How would you modify the function to return the exact probability (equity) of winning rather than just a boolean?
- How would your evaluation logic change if the game allowed community cards shared between players (e.g., Texas Hold'em)?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.