# The Ones That Count

> Not every minute counts. Add up the ones that do.

Canonical URL: <https://datadriven.io/problems/the_ones_that_count>

Domain: Python · Difficulty: easy · Seniority: L5

## Problem

A workout tracker logs each session as a record carrying the activity `name` and its duration in `minutes`. Given the full log and a short list of activity names you actually care about, return the total minutes spent on just those activities.

## Worked solution and explanation

### What this really is

Underneath the ledger costume this is a filter-then-sum: keep only the records whose name is one you care about, then add up their minutes. Everyone gets the arithmetic right. What separates people on a warm-up like this is whether you reach for a set. Check membership against the raw `targets` list and every one of your 10,000 records pays an O(m) scan; the answer is identical but the runtime quietly goes quadratic. The other way to lose points is subtler: forget the filter and sum everything, which passes the tiny example in your head and fails the moment a non-target record slips in.

---

### Break down the requirements

#### Step 1: Convert targets to a set

List membership checks are O(n) per lookup. `set(targets)` gives O(1) average-case, which is what keeps filtering 10K activities against 100 targets linear instead of quadratic.

#### Step 2: Filter and sum in one pass

With the targets in a set, sum the minutes of every activity whose name is in it. A generator expression fed to `sum()` filters and accumulates in one readable pass, no manual running total to manage.

#### Step 3: Let the base case fall out

Empty inputs produce 0 naturally: `sum()` over an empty generator is 0, so no special-case branch is needed. Same story when targets is empty and nothing matches.

---

### The solution

**Set lookup with a generator sum**

```python
def activity_time_ledger(activities: list[dict], targets: list[str]) -> int:
    target_set = set(targets)
    return sum(
        activity['minutes']
        for activity in activities
        if activity['name'] in target_set
    )
```

> **Time and Space Complexity**
>
> **Time:** O(n + m) where n is the number of activities and m is the number of targets. Building the set is O(m), the single pass over activities is O(n), and each lookup is O(1) average.
> 
> **Space:** O(m) for the target set. The generator streams, so there is no intermediate list; accumulation is O(1) extra.

> **Interviewers Watch For**
>
> Do you reflexively hoist `targets` into a `set`? Leaving it as a list is technically correct but signals you are not thinking about the cost of repeated membership tests. On an easy problem this is the single clearest seniority tell.

> **Common Pitfall**
>
> Activity names are case-sensitive: `'Run'` and `'run'` do not match. The prompt does not ask for case-insensitive matching, but naming this edge before you are asked reads as care rather than oversight.

---

## Common follow-up questions

- What if some activity records were missing the 'minutes' key? _(Tests defensive dict access: activity.get('minutes', 0) versus a bracket lookup that raises on a missing key.)_
- How would you return a per-activity breakdown instead of a single total? _(Tests pivoting from a scalar accumulator to a dict accumulator keyed by name.)_
- What if the target match needed to be case-insensitive? _(Tests string normalization: lower-casing both the names and the targets before comparison.)_

## Related

- [All practice problems](https://datadriven.io/problems)
- [Mock interview mode](https://datadriven.io/interview/the_ones_that_count)
- [Python Interview Questions](https://datadriven.io/python-interview-questions)
- [Data Engineering Interview Prep Guide](https://datadriven.io/data-engineer-interview-prep)
- [Daily Challenge](https://datadriven.io/daily)

---

Source: DataDriven (https://datadriven.io). DataDriven is the data engineering interview community. Live code execution in SQL, Python, and Spark sandboxes. Every feature is open to every member.