Down the Line

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
L4

Problem

A round-robin scheduler keeps its consumers in a fixed order and advances the assignment by shift slots each cycle so the load spreads evenly down the line. Given the consumers list and a shift, return the order rotated to the right by shift, so the last shift consumers wrap around to the front. The shift can exceed the roster length or be negative (a left rotation), and an empty roster comes back empty.

Load has to keep moving. Pass it down the line.

Example 1

Input:

consumers = ["ana","bo","cy","dan","ed"], shift = 2

Output:

["dan","ed","ana","bo","cy"]

Example 2

Input:

consumers = ["ana","bo","cy"], shift = 0

Output:

["ana","bo","cy"]

Worked solution and explanation

What this really is

This is a slice-and-swap hiding inside a scheduling story. The skill it probes is whether you normalize shift before you index, so the rotation lands no matter how big or how negative the number is. Anyone can type consumers[-shift:] + consumers[:-shift]. The trap is the moment shift is 7 on a 3-name roster, or shift is negative: index with the raw value and Python clamps the slice to the whole list, so rotating a 5-consumer roster by 7 hands back the original order untouched. It does not crash, it just silently misroutes load, which is the worst kind of bug because it looks like it worked.


Walking to the answer

Step 1: Fold the shift into range

Reduce shift to shift % len(consumers). On a roster of 5, a shift of 7 collapses to 2 and a shift of -1 folds to 4. Python's modulo on a negative left operand already returns a non-negative result, so left rotations turn into their equivalent right rotation for free. Do this first and every later line gets to assume shift is in range.

Step 2: Split at the wrap point and recombine

Take the last shift consumers and put them in front of the rest. consumers[-shift:] is the tail that wraps around, and consumers[:-shift] is everything before it. Put the tail first, then the head. Guard the empty roster up front, because the modulo divides by the length and would crash on zero. Skip a separate zero-shift branch. When shift folds to 0, consumers[-0:] is the whole list and consumers[:-0] is empty, so the same line already returns an unchanged copy.


The solution

Modulo-normalized slice rotation
def rotate_list(consumers, shift):
    if not consumers:
        return []
    shift = shift % len(consumers)
    return consumers[-shift:] + consumers[:-shift]
Raw shift, no modulo
return consumers[-shift:] + consumers[:-shift] With shift=7 on a 5-name roster, consumers[-7:] clamps to the whole list and consumers[:-7] is empty, so you return the original order. No error, wrong answer.
Normalized shift
shift = shift % len(consumers) return consumers[-shift:] + consumers[:-shift] 7 folds to 2 and the wrap point is correct. Negative shifts fold to their right-rotation twin the same way.

Common follow-up questions