No Days Off

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
Asked in
Salesforce

Problem

You're auditing login records from a retention dashboard, where each entry in activities carries a user_id and a date string in 'YYYY-MM-DD' form, and a user can appear more than once on the same day. Return the user_ids who were active across at least min_streak (default 3) back-to-back calendar days, treating repeated dates for one user as a single day. The result comes back sorted alphabetically.

Show up every day. Miss one and the count starts over.

Example

Input:

activities = [{"date":"2024-01-01","user_id":"alice"},{"date":"2024-01-02","user_id":"alice"},{"date":"2024-01-03","user_id":"alice"},{"date":"2024-01-01","user_id":"bob"},{"date":"2024-01-03","user_id":"bob"}], min_streak = 3

Output:

["alice"]

Worked solution and explanation

What this really is

Strip the retention framing and this is classic gaps-and-islands: per user, find the longest run of consecutive calendar days. Anyone can group by user and sort the dates. The trap is the duplicate date: two logins on the same day are ONE day, and if you skip the dedup you either double-count a day toward the streak or, worse, treat the repeat as a zero-day step and quietly inflate the run. Collapse each user's days into a set of distinct dates first, and the streak scan becomes trivial.


Break down the requirements

Step 1: Group activity dates by user

Build a dict mapping each user to their set of unique active dates. The set handles deduplication for free.

Step 2: Sort each user's dates

Consecutive detection only makes sense in chronological order, so sort each user's distinct dates.

Step 3: Find the longest streak per user

Walk the sorted dates and count the run length. Bump the counter when the next date is exactly one day later; reset to 1 the moment a gap appears.

Step 4: Filter users whose streak meets min_streak

Keep only users whose longest run meets min_streak, then return them sorted alphabetically.


The solution

Group, sort, and streak detection
from datetime import datetime, timedelta

def find_streak_users(activities: list[dict], min_streak: int = 3) -> list[str]:
    user_dates = {}
    for record in activities:
        user = record['user_id']
        date = datetime.strptime(record['date'], '%Y-%m-%d').date()
        user_dates.setdefault(user, set()).add(date)
    streak_users = []
    for user, dates in user_dates.items():
        sorted_dates = sorted(dates)
        max_streak = 1
        current_streak = 1
        for i in range(1, len(sorted_dates)):
            if sorted_dates[i] - sorted_dates[i - 1] == timedelta(days=1):
                current_streak += 1
            else:
                current_streak = 1
            if current_streak > max_streak:
                max_streak = current_streak
        if max_streak >= min_streak:
            streak_users.append(user)
    return sorted(streak_users)

Common follow-up questions