The Portfolio

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
L3
Asked in
Airbnb

Problem

A short-term rental marketplace exports its listings, one row per listing with a host and a bed count, and a single host can own several. We're publishing host standings, where a host's standing is the total beds across all of their listings. Produce the standings, biggest hosts first.

Count every bed under a name. The largest holdings rise first.

Example

Input:

listings = [{"beds":8,"host_id":"h2","host_name":"Bob"},{"beds":3,"host_id":"h1","host_name":"Alice"},{"beds":2,"host_id":"h3","host_name":"Carol"},{"beds":5,"host_id":"h1","host_name":"Alice"}]

Output:

[{"rank":1,"host_name":"Alice","total_beds":8},{"rank":1,"host_name":"Bob","total_beds":8},{"rank":2,"host_name":"Carol","total_beds":2}]

Worked solution and explanation

What this really is

Strip away the marketplace framing and this is a two-phase transform wearing a one-line 'rank the hosts' costume. Phase one collapses many listings into one row per host by summing beds; phase two walks those totals in order handing out positions. Anyone can sort a list. The first trap is that a host owns several listings, so positioning the rows as they arrive positions listings, not hosts, and a host with three small rooms leapfrogs a host with one big suite. The second trap: when two hosts tie, arbitrary input order decides who lands first unless you force host_name as the tie-break, so re-shuffling the input silently changes who sits at position 1.


Break it down

Step 1: Aggregate total beds per host

Fold the listings into a dict keyed by host_id, carrying the host_name and a running bed total. This is the step that makes the whole problem about hosts instead of rows.

Step 2: Sort by total, then break ties by name

Sort the aggregated hosts by total beds descending, then host_name ascending. The secondary key is not decoration: without it, two tied hosts come out in whatever order the dict happened to yield, and your output stops being deterministic.

Step 3: Assign no-gap positions

Walk the sorted hosts once, tracking the previous total. Bump the position only when the current total differs from the previous one. Equal totals reuse the current position, and the next distinct total gets the very next number, never skipping.


The solution

Aggregate, sort, and assign positions
def rank_hosts(listings: list) -> list:
    totals = {}
    for row in listings:
        hid = row['host_id']
        if hid not in totals:
            totals[hid] = {'host_name': row['host_name'], 'total_beds': 0}
        totals[hid]['total_beds'] += row['beds']

    ordered = sorted(
        totals.values(),
        key=lambda h: (-h['total_beds'], h['host_name']),
    )

    result = []
    rank = 0
    prev_total = None
    for host in ordered:
        if host['total_beds'] != prev_total:
            rank += 1
            prev_total = host['total_beds']
        result.append({
            'host_name': host['host_name'],
            'total_beds': host['total_beds'],
            'rank': rank,
        })
    return result

Common follow-up questions