# Progress Milestones

> Progress at every 10% increment. Keep the receipts.

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

Domain: Python · Difficulty: easy · Seniority: L5

## Problem

Given a positive integer k, return a list of 10 milestone values at 10%, 20%, ..., 100% of k. Each value is int(k * pct / 100). Return the list of 10 integers in order.

## Worked solution and explanation

### Why this problem exists in real interviews

Milestone bucketing is the simplest possible test of whether you handle integer division correctly and whether you can express a percentage scan as a single comprehension. Interviewers use it as a five minute warmup before harder problems and watch for whether you reach for floats unnecessarily.

---

### Break down the requirements

#### Step 1: Generate the percentage stops

You need 10, 20, ..., 100. `range(10, 101, 10)` gives exactly those ten values. Hard coding the literal list works too but the range form scales if the interviewer asks for 5 percent buckets.

#### Step 2: Use integer division to match the spec

The spec says `int(k * pct / 100)`. Equivalently `k * p // 100` in Python. Multiply before dividing so that small k values do not get truncated to 0 prematurely.

#### Step 3: Return as a list comprehension

A single list comp is the most idiomatic Python: `[k * p // 100 for p in range(10, 101, 10)]`. It reads as 'one milestone per percentage stop' which mirrors the spec sentence for sentence.

---

### The solution

**One line list comprehension**

```python
def progress_milestones(k):
    return [k * p // 100 for p in range(10, 101, 10)]
```

> **Cost Analysis**
>
> Time is O(1) because the loop runs exactly ten times regardless of k. Space is O(1) for the same reason: the output list always has ten entries.

> **Interviewers Watch For**
>
> Whether you multiply before dividing, whether you use `//` instead of `/`, and whether you can articulate why `int(k * p / 100)` and `k * p // 100` agree for non negative inputs but diverge for negatives.

> **Common Pitfall**
>
> Writing `k // 100 * p` collapses small k values to 0 for every milestone. Order of operations matters: scale up first, divide last.

---

## Common follow-up questions

- How would you parameterize the bucket size? _(Add a `step` argument and use `range(step, 101, step)`. Discuss what happens when 100 is not divisible by step.)_
- How would you return the milestones as percentages of progress, not raw counts? _(Pair each value with its percentage: `[(p, k * p // 100) for p in range(10, 101, 10)]`. Useful for progress bar UIs.)_
- What if k can be a float, like total bytes downloaded? _(Drop the floor division and round at the end, or keep floor division by casting input to int. Talk through the precision implications.)_

## Related

- [All practice problems](https://datadriven.io/problems)
- [Mock interview mode](https://datadriven.io/interview/progress_milestones)
- [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.