# Points of Order

> Every page makes its case for the top. Settle it, and settle the ties.

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

Domain: Python · Difficulty: medium · Seniority: L3

## Problem

A web-analytics rollup hands you `views`, a dict mapping each page path to its view count for the day. Return a `[path, count]` pair for every page, ordered from the most-viewed page down to the least. When two pages drew the same number of views, the one whose path comes first alphabetically goes ahead.

## Worked solution and explanation

### What this really is

This is a two-key sort wearing a leaderboard costume. The counts sort one way, biggest first. The paths sort the other way, alphabetical and smallest first, but only when counts tie. That opposition is the entire problem. The lazy answer, `sorted(items, reverse=True)`, flips BOTH directions at once: it does give you counts high-to-low, but it also reverses the path order on ties, so two pages tied at 5 views come back as /login before /blog instead of /blog before /login. It sails through every example without a tie and breaks the instant one appears.

---

### The move that cracks it

#### Step 1: Materialize the pairs

Build the output rows first: one `[path, count]` pair per entry in `views`. A small comprehension over `views.items()` is the clean way, and it leaves the original dict untouched.

#### Step 2: Sort on a composite key

Sort with a tuple key `(-count, path)`. Negating the count gives you descending order on the numbers while keeping the natural ascending order on the path. Python compares the tuple left to right, so path only matters when the negated counts are equal. One sort, both rules.

**Composite-key sort: count descending, path ascending**

```python
def rank_pages(views):
    return sorted(
        ([path, count] for path, count in views.items()),
        key=lambda pair: (-pair[1], pair[0]),
    )
```

> **Trick to solving**
>
> The whole trick is the sign flip. `-pair[1]` turns 'largest count first' into a plain ascending sort, which lets the second element of the tuple, the path, stay ascending too. Opposite directions in one key, no second pass.

> **Common pitfall**
>
> `reverse=True` reverses the entire ordering, including your tie-break. Candidates reach for it because it reads cleanly, then ship output where tied pages come out in reverse-alphabetical order. The composite key is what separates someone who has been bitten by this from someone who hasn't.

**reverse=True (wrong on ties)**

sorted(pairs, key=lambda p: p[1], reverse=True). Ties at 5: /login, /blog. The reverse flag dragged the path order backwards.

**tuple key (correct)**

sorted(pairs, key=lambda p: (-p[1], p[0])). Ties at 5: /blog, /login. Count descends, path still ascends.

> **Performance insight**
>
> **Time:** O(n log n) for the single sort, where n is the number of pages.
> 
> **Space:** O(n) for the list of pairs and the sorted result. The input dict is never mutated.

---

## Common follow-up questions

- What if you only need the top 10 pages instead of the full ordering? _(Pushes toward heapq.nlargest(k, views.items(), key=lambda p: p[1]) for O(n log k), and a discussion of how to keep the same tie-break under a heap.)_
- How does your tie-break survive if you switch to a heap-based top-k? _(Tests whether the candidate sees that a plain heap or nlargest does not honor the secondary ascending key without extra care.)_
- What changes if the view counts stream in and update throughout the day? _(Tests maintaining order incrementally with a structure like a SortedList rather than re-sorting on every change.)_

## Related

- [All practice problems](https://datadriven.io/problems)
- [Mock interview mode](https://datadriven.io/interview/points_of_order)
- [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.