# The Yahtzee Engine

> Five dice. Six faces. Score it.

Canonical URL: <https://datadriven.io/problems/the_yahtzee_engine>

Domain: Python · Difficulty: hard · Seniority: L4

## Problem

Given 5 dice, return a dict with scores for all Yahtzee categories: 'ones' through 'sixes' (sum of matching dice), 'three_of_a_kind' (sum of all if >=3 match else 0), 'four_of_a_kind', 'full_house' (25 if 3+2 pattern), 'small_straight' (30 if 4 consecutive), 'large_straight' (40 if 5 consecutive), 'yahtzee' (50 if all 5 match), 'chance' (sum of all).

## Worked solution and explanation

### Why this problem exists in real interviews

This tests **categorical scoring logic**, **frequency analysis**, and **conditional branching**. Implementing a full Yahtzee scorer requires mapping game rules to code, probing whether a candidate can translate complex specifications into clean, organized logic.

---

### Break down the requirements

#### Step 1: Count die face frequencies

Build a frequency dict from the five dice values. Most categories depend on these frequencies.

#### Step 2: Implement upper section scoring (ones through sixes)

Sum dice matching the target face value.

#### Step 3: Implement n-of-a-kind, full house, and Yahtzee

Check max frequency for n-of-a-kind. Full house requires exactly 3+2. Yahtzee requires all 5 matching.

#### Step 4: Implement straights

Small straight needs 4 consecutive values. Large straight needs 5 consecutive. Check using sorted unique values.

#### Step 5: Implement chance

Sum of all dice regardless of pattern.

---

### The solution

**Frequency-driven categorical scoring engine**

```python
def yahtzee_scores(dice: list) -> dict:
    freq = {}
    for d in dice:
        freq[d] = freq.get(d, 0) + 1
    total = sum(dice)
    max_freq = max(freq.values())
    unique_sorted = sorted(freq.keys())
    scores = {}
    names = ["ones", "twos", "threes", "fours", "fives", "sixes"]
    for i in range(6):
        face = i + 1
        count = freq.get(face, 0)
        scores[names[i]] = face * count
    scores["three_of_a_kind"] = total if max_freq >= 3 else 0
    scores["four_of_a_kind"] = total if max_freq >= 4 else 0
    freq_values = sorted(freq.values())
    scores["full_house"] = 25 if freq_values == [2, 3] else 0
    has_small = False
    for start in [1, 2, 3]:
        run = True
        for v in range(start, start + 4):
            if v not in freq:
                run = False
                break
        if run:
            has_small = True
            break
    scores["small_straight"] = 30 if has_small else 0
    has_large = False
    for start in [1, 2]:
        run = True
        for v in range(start, start + 5):
            if v not in freq:
                run = False
                break
        if run:
            has_large = True
            break
    scores["large_straight"] = 40 if has_large else 0
    scores["yahtzee"] = 50 if max_freq == 5 else 0
    scores["chance"] = total
    return scores
```

> **Time and Space Complexity**
>
> **Time:** O(1). The input is always 5 dice with values 1-6, making all operations bounded by constants.
> 
> **Space:** O(1). The frequency dict and scores dict have bounded size.

> **Interviewers Watch For**
>
> Clean organization of scoring categories. Mixing upper section, n-of-a-kind, and straight logic into a single tangled block is a red flag for code quality.

> **Common Pitfall**
>
> Full house detection: `[2, 3]` frequency pattern only. A Yahtzee (all 5 same) has frequency `[5]`, which is NOT a full house. Some candidates incorrectly treat 5-of-a-kind as a full house.

---

## Common follow-up questions

- How would you add bonus Yahtzee scoring? _(Tests tracking whether the player already scored a Yahtzee and applying the 100-point bonus.)_
- What if you needed to recommend the best category for a given roll? _(Tests iterating all categories and selecting the maximum score.)_
- How would you extend this to support custom dice (e.g., 8-sided)? _(Tests parameterizing the face range and adjusting straight detection.)_
- How would you implement the full game state with 13 rounds? _(Tests stateful class design tracking used categories and cumulative score.)_

## Related

- [All practice problems](https://datadriven.io/problems)
- [Mock interview mode](https://datadriven.io/interview/the_yahtzee_engine)
- [Python Interview Questions](https://datadriven.io/python-interview-questions)
- [Data Engineering Interview Prep Guide](https://datadriven.io/data-engineer-interview-prep)
- [Daily Challenge](https://datadriven.io/daily)

---

Source: DataDriven (https://datadriven.io). 100% free data engineering interview prep. Live code execution against Postgres 16, Python 3.11, and Spark sandboxes. No paywall, no premium tier, no signup gate.