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 = 3Output:
["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
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
- What if the threshold were configurable? (Tests parameterization: pass the streak length as an argument.)
- How would you also return the streak dates? (Tests tracking the start index of the current streak.)
- What if activity timestamps include hours and you need to bucket by date? (Tests date truncation from datetime objects.)
- How would this work on a billion-row event log? (Tests partitioned processing or database-level window functions.)