The Carousel

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

Domain
Python
Difficulty
easy
Seniority
L3

Problem

A status display cycles through a fixed ring of items, and you need to advance its starting point by k slots so the item currently sitting k places along becomes the new front. Return a fresh list holding that left rotation, where k may be zero, larger than the length of lst, or negative (a negative k shifts the ring the other way). An empty lst comes back empty.

Keep moving, same ride.

Example 1

Input:

lst = [1,2,3,4,5], k = 2

Output:

[3,4,5,1,2]

Example 2

Input:

lst = ["a","b","c"], k = 1

Output:

["b","c","a"]

Worked solution and explanation

What this problem really is

Underneath the carousel costume, this is index normalization. The rotation itself is one slice-and-concatenate; the part that actually separates candidates is taming k before you touch the list. A k of 7 on a 3-element list, or a k of -1, both have to land on a clean offset inside [0, n). Get the normalization wrong and you either throw or hand back garbage.


How to get there

Step 1: Bail out on empty input

Guard the empty list first. len([]) is 0, and any modulo against 0 raises ZeroDivisionError, so the empty case has to return before you compute an offset.

Step 2: Normalize the offset

Collapse k into k % len(lst). In Python the result is always in [0, n) even when k is negative, so an oversized or negative k both reduce to the same small left-shift without any special branch.

Step 3: Slice and recombine

Everything from the offset onward comes first, then everything before it. lst[k:] + lst[:k] is the whole rotation in one expression.


The solution

Modulo-normalized left rotation
def rotate_left(lst, k):
    if not lst:
        return []
    k = k % len(lst)
    return lst[k:] + lst[:k]

One modulo absorbs oversized and negative k; one slice does the rest.

Naive
return lst[k:] + lst[:k] with no modulo. Works for the example inputs, then silently no-ops: once k reaches or exceeds n, lst[k:] is empty and lst[:k] is the whole list, so it hands back the original order (for k=3 on [1,2,3] you get [1,2,3], not the rotated list). Large negative k fails the same way.
Normalized
k = k % len(lst) first. Every k, large or negative, maps onto one canonical offset in [0, n), and the same slice expression is now always correct.

Common follow-up questions