The Progress Meter

A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.

Domain
Python
Difficulty
medium
Seniority
L3
Asked in
Stitch Fix

Problem

A long-running batch job logs a cumulative reading after each item it finishes, and we want a fixed ten-point progress summary no matter how many readings a run produced. Given the readings in order, return the value standing at each ten-percent mark through the list, from the 10% mark up to the 100% mark.

Ten glimpses of a run, no matter how long it ran.

Example 1

Input:

readings = [3,8,15,22,30,41,55,60,72,80,88,95,103,110,118,125,130,142,150,160]

Output:

[8,22,41,60,80,95,110,125,142,160]

Example 2

Input:

readings = [100,250,400]

Output:

[100,100,100,250,250,250,400,400,400,400]

Worked solution and explanation

What this problem really is

This is quantile sampling wearing a progress-bar costume. The real question: can you drop ten evenly spaced sample points onto a list whose length you don't control? Everyone reaches for readings[::step] with step = len(readings) // 10, and it betrays them the moment the length isn't a clean multiple of ten. The slice yields the wrong count, drifts off the last element, and divides by zero when the list is shorter than ten. The move that works is to compute each mark's index straight from the length with a ceiling division, so the 100% mark always lands on the last reading and short runs repeat values instead of crashing.


Why the obvious approach breaks

Fixed-step slice (wrong)
step = len(readings) // 10; readings[step-1::step]. For a length of 3 the step is 0 and you crash. For a length of 25 the step is 2 and you get 12 or 13 points, not 10, and the last one is nowhere near 100%.
Per-mark index (right)
For each mark k in 1..10, compute the index (k * n - 1) // 10. The count is pinned at ten by construction, the k=10 mark is always the final element, and n < 10 simply repeats indices.

Step 1: Turn each mark into an index

The k-th ten-percent mark is at position ceil(k * n / 10), counted from one. Convert to a zero-based index by subtracting one: ceil(k*n/10) - 1 is exactly (k*n - 1) // 10, so a single integer expression gives every mark with no floats and no rounding drift.

Step 2: Collect the ten samples

Walk k from 1 to 10 and read readings at that index. Ten iterations, independent of input length, so the answer is always ten values in mark order.


The solution

Ceiling-division decile sampling
def progress_milestones(readings: list) -> list:
    n = len(readings)
    # ceil(k * n / 10) - 1: index of the k-th 10% mark, rounded up, zero-based
    return [readings[(k * n - 1) // 10] for k in range(1, 11)]

Common follow-up questions