S3Q1 · Workout Data Analytics¶
⚡ Quick Reference
Function: filter_workouts(data: dict, category: str) -> set
Core idea: For each user, compute avg / min / max of their durations, then test the condition for the requested category.
def filter_workouts(data, category):
result = set()
for user, durations in data.items():
avg = sum(durations) / len(durations)
mn, mx = min(durations), max(durations)
if category == 'fitness_enthusiast' and avg >= 90: result.add(user)
elif category == 'regular_user' and 45 <= avg < 90: result.add(user)
elif category == 'consistent_workout' and mn >= 30: result.add(user)
elif category == 'balanced_routine' and mx - mn <= 20: result.add(user)
return result
Key rules:
- fitness_enthusiast: avg >= 90
- regular_user: 45 <= avg < 90 (both bounds include/exclude carefully)
- consistent_workout: every session >= 30, so min >= 30
- balanced_routine: max - min <= 20
Problem Statement¶
Problem
Given a dictionary data mapping user names to lists of workout durations (minutes), return a set of user names matching the given category:
'fitness_enthusiast'-- average duration >= 90'regular_user'-- average duration in [45, 90) -- 45 inclusive, 90 exclusive'consistent_workout'-- every duration >= 30'balanced_routine'-- max duration - min duration <= 20
Example:
data = {
"Aditi": [100, 95, 90],
"Bharat": [50, 60, 55],
"Chetan": [120, 130, 125],
"Divya": [35, 40, 45],
"Esha": [20, 55, 25]
}
filter_workouts(data, 'fitness_enthusiast')
{'Aditi', 'Chetan'}
filter_workouts(data, 'consistent_workout')
{'Aditi', 'Bharat', 'Chetan', 'Divya'}
Understanding the problem¶
Each category maps to a different statistic. Compute all three statistics once per user, then check the relevant one:
| Statistic | Used by |
|---|---|
avg = sum / len |
fitness_enthusiast, regular_user |
min(durations) |
consistent_workout |
max - min |
balanced_routine |
Full trace of all five users:
| User | Durations | Avg | Min | Max-Min | FE | RU | CW | BR |
|---|---|---|---|---|---|---|---|---|
| Aditi | [100,95,90] | 95 | 90 | 10 | ✅ | ✅ | ✅ | |
| Bharat | [50,60,55] | 55 | 50 | 10 | ✅ | ✅ | ✅ | |
| Chetan | [120,130,125] | 125 | 120 | 10 | ✅ | ✅ | ✅ | |
| Divya | [35,40,45] | 40 | 35 | 10 | ✅ | ✅ | ||
| Esha | [20,55,25] | 33.3 | 20 | 35 |
consistent_workout uses min(), not avg()
The condition is that every session is >= 30. Checking the minimum is sufficient -- if the shortest session passes, all sessions pass. You don't need an all(d >= 30 for d in durations) loop; min(durations) >= 30 is equivalent and O(n) in one pass.
regular_user boundary: 45 inclusive, 90 exclusive
45 <= avg < 90 -- read the problem carefully. A user with exactly avg 90 is a fitness_enthusiast, not a regular_user. Divya (avg 40) falls into neither category.
Solution approaches¶
def filter_workouts(data: dict, category: str) -> set:
result = set()
for user, durations in data.items():
avg = sum(durations) / len(durations)
minimum = min(durations)
maximum = max(durations)
spread = maximum - minimum
if category == 'fitness_enthusiast':
if avg >= 90:
result.add(user)
elif category == 'regular_user':
if 45 <= avg < 90:
result.add(user)
elif category == 'consistent_workout':
if minimum >= 30: # min >= 30 means all values >= 30
result.add(user)
elif category == 'balanced_routine':
if spread <= 20:
result.add(user)
return result
def filter_workouts(data: dict, category: str) -> set:
conditions = {
'fitness_enthusiast': lambda d: sum(d) / len(d) >= 90,
'regular_user': lambda d: 45 <= sum(d) / len(d) < 90,
'consistent_workout': lambda d: min(d) >= 30,
'balanced_routine': lambda d: max(d) - min(d) <= 20,
}
test = conditions[category]
return {user for user, durations in data.items() if test(durations)}
def filter_workouts(data: dict, category: str) -> set:
avg = lambda d: sum(d) / len(d)
test = {
'fitness_enthusiast': lambda d: avg(d) >= 90,
'regular_user': lambda d: 45 <= avg(d) < 90,
'consistent_workout': lambda d: min(d) >= 30,
'balanced_routine': lambda d: max(d) - min(d) <= 20,
}[category]
return {u for u, d in data.items() if test(d)}
Key takeaways¶
Use min() for "every element" conditions
Checking min(durations) >= 30 is equivalent to all(d >= 30 for d in durations) but more concise. The same pattern applies to any "all values above threshold" check.
Dict of lambdas for dispatch
Mapping category strings to lambda functions replaces a chain of if/elif blocks. Look up the right function with conditions[category], then apply it -- clean and easy to extend with new categories.
Set comprehension for filtering
{user for user, d in data.items() if condition(d)} builds the result set in one expression. It reads as: "give me the users where the condition holds" -- closer to the problem description than an explicit loop.