Compare Complete or Partial Hands
Company: Rippling
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Onsite
Implement a hand comparison engine for a simplified poker-like card game.
Each player has a hand represented by an array of card strings. A card is encoded as `<rank><suit>`, where rank is one of `2-10`, `J`, `Q`, `K`, `A`, and suit is one of `S`, `H`, `D`, `C`.
## Part 1: Compare complete hands
If both players have exactly 5 cards, return one of:
- `"user1"` if player 1 wins
- `"user2"` if player 2 wins
- `"tie"` if the hands are exactly equal in strength
Use the following hand rankings from strongest to weakest:
1. Four of a kind
2. Full house
3. Three of a kind
4. Two pair
5. One pair
6. High card
Tie-breaking rules:
- **Four of a kind**: compare the rank of the four matching cards, then the kicker.
- **Full house**: compare the rank of the triple, then the pair.
- **Three of a kind**: compare the rank of the triple, then the remaining two cards in descending order.
- **Two pair**: compare the higher pair, then the lower pair, then the kicker.
- **One pair**: compare the pair rank, then the remaining three cards in descending order.
- **High card**: compare all five ranks in descending order.
Assume suits do not affect hand strength.
## Part 2: Compare partial hands
Because of network delay, a player may have fewer than 5 received cards. In this case, determine whether the result is already forced.
Return:
- `"user1"` if player 1 wins for **every** valid completion of the missing cards
- `"user2"` if player 2 wins for **every** valid completion of the missing cards
- `"tie"` if **every** valid completion ends in a tie
- `"unknown"` otherwise
For this follow-up, assume:
- Each final hand must contain exactly 5 distinct cards.
- Missing cards can be any distinct cards from the remaining standard 52-card deck.
- No card may appear twice across the final 10 cards.
Design the comparison logic cleanly so that ranking rules are modular and easy to extend.
Quick Answer: This question evaluates implementation of card-hand evaluation logic, combinatorial reasoning about incomplete information, and deterministic tie-breaking rules for comparing complete and partial poker-like hands.
Part 1: Compare Complete Hands
Implement a hand comparison engine for a simplified poker-like card game.
Each player has exactly 5 cards. A card is encoded as '<rank><suit>', where rank is one of 2-10, J, Q, K, A, and suit is one of S, H, D, C.
Suits do not affect hand strength. Only the following hand types exist, from strongest to weakest:
1. Four of a kind
2. Full house
3. Three of a kind
4. Two pair
5. One pair
6. High card
Tie-breaking rules:
- Four of a kind: compare the rank of the four matching cards, then the kicker.
- Full house: compare the rank of the triple, then the pair.
- Three of a kind: compare the triple, then the remaining two cards in descending order.
- Two pair: compare the higher pair, then the lower pair, then the kicker.
- One pair: compare the pair rank, then the remaining three cards in descending order.
- High card: compare all five ranks in descending order.
Return 'user1' if player 1 wins, 'user2' if player 2 wins, or 'tie' if the hands are exactly equal in strength.
Constraints
- len(user1) == 5
- len(user2) == 5
- Each card is a valid standard 52-card deck card
- All 10 cards are distinct
- This simplified game does not include straights, flushes, or suit-based scoring
Examples
Input: (['AS', 'AH', 'AD', 'AC', '2S'], ['KS', 'KH', 'KD', 'KC', 'QH'])
Expected Output: 'user1'
Explanation: Both hands are four of a kind; four aces beats four kings.
Input: (['QS', 'QH', 'QD', '9C', '2D'], ['JS', 'JH', 'JD', '8C', '8D'])
Expected Output: 'user2'
Explanation: A full house beats three of a kind.
Input: (['AS', 'KD', 'QH', '9C', '2D'], ['AH', 'KC', 'QS', '9D', '2C'])
Expected Output: 'tie'
Explanation: Both hands are high card with the same ranks: A, K, Q, 9, 2.
Input: (['AS', 'AH', 'KD', 'QC', '2S'], ['AD', 'AC', 'KS', 'QD', '3H'])
Expected Output: 'user2'
Explanation: Both hands have one pair of aces. Compare kickers: K, Q, 3 beats K, Q, 2.
Hints
- Count how many times each rank appears. The sorted frequency pattern tells you the hand category.
- Create a score tuple like (category_strength, tie_break_values...) so two hands can be compared lexicographically.
Part 2: Compare Partial Hands
Implement a hand comparison engine for a simplified poker-like card game when some cards have not arrived yet.
Each player has a partial hand represented by a list of card strings. A card is encoded as '<rank><suit>', where rank is one of 2-10, J, Q, K, A, and suit is one of S, H, D, C.
Each final hand must contain exactly 5 distinct cards. Missing cards can be any distinct cards from the remaining standard 52-card deck, and no card may appear twice across the final 10 cards.
Use these hand rankings, from strongest to weakest:
1. Four of a kind
2. Full house
3. Three of a kind
4. Two pair
5. One pair
6. High card
Tie-breaking rules:
- Four of a kind: compare the rank of the four matching cards, then the kicker.
- Full house: compare the rank of the triple, then the pair.
- Three of a kind: compare the triple, then the remaining two cards in descending order.
- Two pair: compare the higher pair, then the lower pair, then the kicker.
- One pair: compare the pair rank, then the remaining three cards in descending order.
- High card: compare all five ranks in descending order.
Return:
- 'user1' if player 1 wins for every valid completion
- 'user2' if player 2 wins for every valid completion
- 'tie' if every valid completion ends in a tie
- 'unknown' otherwise
For this version, the total number of missing cards across both players is at most 4.
Constraints
- 0 <= len(user1) <= 5
- 0 <= len(user2) <= 5
- All provided cards are valid standard deck cards
- All provided cards are distinct across both lists
- (5 - len(user1)) + (5 - len(user2)) <= 4
- Each final hand must have exactly 5 cards, and all 10 final cards must be distinct
- This simplified game does not include straights, flushes, or suit-based scoring
Examples
Input: (['AS', 'AH', 'AD', 'AC', '2S'], ['KS', 'KH', 'KD', '3C'])
Expected Output: 'user1'
Explanation: Player 2 can still complete to four kings, but four aces always beats it. So player 1 is forced to win.
Input: (['2S', '2H', '3D', '4C'], ['KS', 'KH', 'KD', 'QC', 'QD'])
Expected Output: 'user2'
Explanation: Player 2 already has a full house. Player 1, with one missing card, can reach at best three of a kind.
Input: (['AS', 'AH', '9D', '5C', '2S'], ['KS', 'KH', 'QD', 'JC'])
Expected Output: 'unknown'
Explanation: If player 2 receives a king, they make three of a kind and win. If they receive a low unrelated card, player 1's pair of aces wins.
Input: (['AS', 'KD', 'QH', '9C', '2D'], ['AH', 'KC', 'QS', '9D', '2C'])
Expected Output: 'tie'
Explanation: No cards are missing. The only completion is the current state, and the hands tie.
Hints
- Reuse a complete-hand evaluator from Part 1. The hard part here is exploring all valid completions.
- If you ever find two different outcomes across valid completions, you can stop early and return 'unknown'.