Rank five-card hands by type, then find best and worst completions of unknown cards
Company: Rippling
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Technical Screen
A card game similar to poker compares hands of five cards. You first write the comparison between two players' hands, then extend it to hands whose last cards are not known yet.
Each card is one character with one of 13 ranks, from lowest to highest: `2 3 4 5 6 7 8 9 T J Q K A`. Cards have no suits, and a rank may appear any number of times in a hand. Every hand has exactly one type, and the types have a fixed priority, strongest first:
| Type | Meaning | Example |
| --- | --- | --- |
| Five of a kind | All five cards share one rank | `77777` |
| Four of a kind | Four cards share one rank | `Q9QQQ` |
| Full house | Three cards of one rank and two of another | `5T55T` |
| Three of a kind | Three cards of one rank; the other two differ from it and from each other | `J8JJ2` |
| Two pair | Two cards of one rank, two of another, and one different card | `4K4KA` |
| One pair | Two cards share one rank; the other three are all different | `63A9A` |
| High card | All five ranks are different | `2795K` |
A hand of a stronger type always beats a hand of a weaker type. Two hands of the same type are compared card by card in the order written: the first position where they differ decides, and the higher rank wins. For example, `2AAAA` loses to `33332`, because both are four of a kind and their first cards are `2` and `3`. Two identical hands tie. Straights and flushes do not exist in this game, so `23456` is a high-card hand.
### Constraints and Clarifications
- The interview described the rules only as poker-like: hand types have a fixed priority, and hands of the same type are compared by card values. The ranks, the type list and the card-by-card tie-break above are this version's assumptions; confirm them before coding.
- A complete hand is a string of exactly five rank characters.
### Clarifying Questions
- When two hands have the same type, are they compared card by card in the order written, or poker-style by the ranks of their groups (the higher pair first)?
- Do straights or flushes count?
- Is the number of cards of one rank limited, as in a real deck with four of each?
- What should happen on malformed input, such as a wrong length or an unknown character?
### Part 1 — Compare two players' hands
Write `compare(hand1: str, hand2: str) -> int` that returns `1` if the first player's hand wins, `-1` if the second player's hand wins, and `0` if they tie.
```hint Read the type from what matters
Decide which information about a hand fully determines its type, regardless of the order in which the cards are written.
```
```hint One comparable value per hand
Look for a single value per hand that captures both the type and the tie-break, so that comparing two hands becomes one comparison.
```
#### What This Part Should Cover
- Classifying a hand into its type
- Ordering the rank characters correctly, including the letter ranks
- The tie-break exactly as specified, and the result for identical hands
- Tests that cover every type and the boundaries between neighboring types
### Part 2 — Best and worst completions of a partial hand
Now some cards at the end of a hand are unknown and written as `?`, for example `KK7??`. Each `?` can become any rank. Write `best_and_worst(partial: str)` that returns the strongest and the weakest complete hand the partial hand could turn into under the Part 1 ordering, together with the type of each. A hand with no `?` is its own best and worst completion.
For example, `2345?` can become `23455` (one pair), its strongest completion, or `23456` (high card), its weakest.
```hint Count the possibilities
Work out how many completions there can be at most, and whether trying all of them is acceptable before reaching for something smarter.
```
```hint One card at a time
Before optimizing, reason about how adding a single card can change a hand's type, and which choices raise it the most or the least.
```
#### Clarifying Questions for this Part
- Are the unknown cards always at the end of the hand, or can they appear anywhere?
- Should the answer be the best and worst complete hands, only their types, or the best and worst outcome against a known opponent hand?
- Can the whole hand be unknown?
#### What This Part Should Cover
- Best and worst defined by the full Part 1 ordering, not by type alone
- A method that finds both completions, with its cost compared with trying every completion
- Edge cases: no unknown cards, every card unknown, and several completions of the same type
### What a Strong Answer Covers
- Part 1's ordering reused unchanged as the single source of truth in Part 2
- Code organized around a type classifier and a hand-strength value that can be tested in isolation
- Tests that would catch two type priorities being swapped, such as full house and four of a kind
- The cost of each part stated in terms of the number of unknown cards
- Assumptions stated explicitly wherever the rules were left open
### Follow-up Questions
- Given an opponent's complete hand, decide whether the partial hand is certain to win, certain to lose, or could go either way.
- How does your code change if hands of the same type are compared poker-style, by the ranks of their groups, instead of card by card?
- If the deck is real, with four cards of each rank, how do the best and worst completions change?
- How would you rank a list of many thousands of hands from weakest to strongest, and what does it cost?
Overview: A two-part coding question on a poker-like card game: compare two five-card hands by a fixed type priority with ties broken card by card, then find the best and worst complete hands when the last cards are unknown. Tests hand classification, ordering keys, testing discipline and search over completions.
Community answers
Answer by snghankitkumar
/*
Rank by priority -> 2 hands of same type needs one by one comparison
CardGame class
Private:
getType
tieBraker
Public:
compare
*/
/*
What about malformed queries?
Could have added validate function + Try to build on top of folder functions you have added
*/
#include
using namespace std;
typedef pair charCount;
class CardGame
{
private:
inline static unordered_map charPriority =
{{'2', 2}, {'3', 3}, {'4', 4}, {'5', 5}, {'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'T', 10}, {'J', 11}, {'Q', 12}, {'K', 13}, {'A', 14}};
struct minComparator
{
bool operator()(const charCount &a, const charCount &b)
{
if (a.first == b.first)
return charPriority[a.second] > charPriority[b.second];
return a.first > b.first;
}
};
struct maxComparator
{
bool operator()(const charCount &a, const charCount &b)
{
if (a.first == b.first)
return charPriority[a.second] < charPriority[b.second];
return a.first < b.first;
}
};
int getType(string s)
{
vector characterFrequency(256, 0);
for (char c : s)
characterFrequency[c]++;
vector frequency;
for (int i = 0; i < 256; i++)
{
if (characterFrequency[i] != 0)
frequency.push_back(characterFrequency[i]);
}
sort(frequency.begin(), frequency.end(), greater<>());
if (frequency[0] == 5)
{
return 1;
}
else if (frequency[0] == 4)
{
return 2;
}
else if (frequency[0] == 3)
{
if (frequency[1] == 2)
return 3;
else
return 4;
}
else if (frequency[0] == 2)
{
if (frequency[1] == 2)
return 5;
else
return 6;
}
else
return 7;
}
int tieBraker(string s1, string s2)
{
for (int i = 0; i