Design poker-like hand comparison with custom ranking
RipplingSoftware Engineer · Technical ScreenLast updated
This question evaluates object-oriented design, rule-based comparison logic, and algorithmic reasoning for ranking and tie-breaking of card hands, including skills in extensibility and comparison-key representation.
Problem
Design an object-oriented solution to compare two players' hands in a card game similar to poker.
You are given two hands (each a fixed number of cards; assume 5 unless you state otherwise). Each hand has a hand type (e.g., three-of-a-kind, pair, full house, etc.). Your design must compare hands, decide a winner (or a tie), and remain extensible so that new hand types and new ruleset orderings can be added without rewriting the comparison engine.
The deliverable is a design plus reference implementation sketch: sketch the class/module breakdown (key classes, interfaces, responsibilities), describe the comparison logic (including tie-break rules and how you represent a hand's "comparison key"), and explain how the extension mechanism in Part 2 fits in.
Constraints & Assumptions
- Hand size: assume 5 cards per hand unless you state otherwise; do not hard-code the size into the core logic.
- Card ranks are totally ordered (e.g.,
2..A, with ace high by default). Suits exist and may be referenced if needed. - A single standard deck: no two cards share the same (rank, suit) identity, but rank collisions across suits are expected (that is what produces pairs, trips, etc.).
- Type precedence is per-ruleset, not global: the same registered types may rank differently in different games.
- The deliverable is a design plus reference implementation sketch, not a hardened production library; favor clarity and extensibility over micro-optimization.
Clarifying Questions to Ask
- Is the hand size always 5, or should the design support other fixed sizes (e.g., 7-card games)?
- Does
add_typereceive only amatches-style detector, or may I also supply a per-type scoring/tie-break function? (This materially changes the design.) - Is a single standard deck assumed, or can hands contain duplicate card identities or wild cards / jokers?
- How should ace be treated — strictly high, or should an ace-low straight (the
A-2-3-4-5"wheel") be supported? - On an exact tie (identical strength), is the result a tie/split, or does the ruleset ever break ties by suit?
- Is
evaluation_ordersguaranteed to cover every hand a player could hold (i.e., is there always a catch-all type), or must I handle "matches no type"?
Part 1 — Comparison and ranking
Implement the core comparison so that, given two hands, you can return which one is larger or whether they tie.
- Compare two hands and return which one is larger (or if they tie).
- If the two hands have different types, the winner is decided by the type ranking (e.g., full house > three-of-a-kind, etc.).
- If the two hands have the same type, break ties by comparing the relevant card ranks in order.
- Example: for three-of-a-kind,
8883xshould beat7773xbecause the 8-trip outranks the 7-trip (assume remaining kickers are compared after the trips if needed).
Part 2 — Extension mechanism
Make the type system pluggable so new hand types and new rulesets do not require touching the engine.
- Implement
add_type(type_id: string, matches_function: function)that registers a new hand type and how to detect it. - The main
evaluatefunction takes an extra parameterevaluation_orders: array<string>that specifies the type precedence (strongest to weakest) used when comparing hands, allowing different games/rulesets to be expressed as data rather than code. - Explain how
add_type(...)andevaluation_orderswork together to classify a hand and place it in the ranking.
Hints
Hint 1
Reduce comparison to one comparable value: Cross-type comparison and same-type tie-breaking feel like two different problems. Can a hand's full strength instead be reduced to **one comparable value**, so that both cases collapse into a single comparison? Think about what that value would have to encode.
Hint 2
Making same-type tie-breaks generic: You could write bespoke tie-break logic for each type (pair, two-pair, trips, full house, quads), but that's a lot of near-duplicate code. Is there **one rule over a hand's repeated ranks** that produces the right ordering for all of them at once — including the `8883x` vs `7773x` case? What property of the matched cards does every count-based tie-break actually key on?
Hint 3
Separate "what exists" from "what ranks higher": There are two distinct facts here: *which types exist and how to recognize them*, versus *which type beats which in this particular game*. Which of these belongs in the registry, and which should be supplied per call so a new game needs no code change? Keeping them apart is the point of the exercise.
Hint 4
Is a boolean enough to break ties?: A boolean `matches_function` can tell you a hand *is* a three-of-a-kind — but is that enough to decide a winner **between two** three-of-a-kinds? If you think it isn't, say so explicitly, and consider what the registration API would need to give you to close the gap.
Hint 5
When more than one predicate fires: A loosely written predicate (e.g. "contains a triple") can match a full house *and* a three-of-a-kind at the same time. If two registered types both claim the same hand, what makes your classification **deterministic** rather than arbitrary? Think about how `evaluation_orders` and the matching loop could interact to settle it.
Follow-up questions
- How does your design change for **Texas Hold'em**, where each player forms the best 5-card hand out of 7 available cards?
- A hand satisfies **multiple** type predicates at once (e.g., a permissive "contains a triple"). How does your design guarantee a deterministic, correct classification?
- How would you support **suit-based tie-breaking** in a ruleset that uses it, without disturbing rulesets that don't?
- How would you handle **wild cards / jokers** that can stand in for any rank?
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.