Sign in to run and submit your work
Reading is open to everyone. Running code and saving drafts need an account so your work is yours and comes back on your next visit.
or
CODE WORKSPACE
An on-call engineer is staring at fifty thousand log lines and cannot see the pattern for the noise, because every line carries a different job id, retry counter or key. They want the lines grouped by template — the message with its numbers masked — so the loudest kind of message is at the top.
Write group_by_template(lines). It takes lines, a list of raw log-line strings in the order they were written, and returns a list of dicts {"template": str, "count": int, "first_seen": int}, one per distinct template.
Function to write
group_by_template(lines: list[str]) -> list[dict]One dict per template with its count and first index, ordered by count descending then first_seen ascending.
How to approach it
Turn each line into its template first — mask digit runs, collapse whitespace — and use that string as the dict key. Everything else is counting.
Sample cases
+ 2 held back until you submit
retry counters are one template
Three retry lines differ only in their numbers, so they are one template seen 3 times.
Input
Argument 1
[
'retry 3 of 5',
'job 17 started',
'retry 4 of 5',
'job 18 started',
'retry 1 of 5',
'disk full'
]Returns
| template | count | first_seen |
|---|---|---|
| retry <n> of <n> | 3 | 0 |
| job <n> started | 2 | 1 |
| disk full | 1 | 5 |
digits glued to a word
A digit run inside a word is still masked: user42 and user7 both become user<n>.
Input
Argument 1
[
'user42 logged in',
'user7 logged in',
'user42 logged out'
]Returns
| template | count | first_seen |
|---|---|---|
| user<n> logged in | 2 | 0 |
| user<n> logged out | 1 | 2 |
spacing differs, the template does not
A double space, padding and a tab all collapse to one space, and 30s becomes <n>s.
Input
Argument 1
[
'cache miss for key 9',
' cache miss for key 10 ',
'cache miss for key 11',
'timeout after 30s'
]Returns
| template | count | first_seen |
|---|---|---|
| cache miss for key <n> | 3 | 0 |
| timeout after <n>s | 1 | 3 |
a tie on count goes to the first seen
Both templates have 2 lines; worker <n> idle appeared first, so it comes first, not alphabetically.
Input
Argument 1
[
'worker 2 idle',
'flush 10 rows',
'flush 12 rows',
'worker 5 idle'
]Returns
| template | count | first_seen |
|---|---|---|
| worker <n> idle | 2 | 0 |
| flush <n> rows | 2 | 1 |
no lines
An empty log returns an empty list rather than None.
Input
Argument 1
[] (empty list)
Returns
[] (empty list)
Constraints
<n>, then every run of any whitespace collapsed to a single space, then stripped. "retry 3 of 5" becomes "retry <n> of <n>"."user42 logged in" becomes "user<n> logged in", and "30s" becomes "<n>s".count is how many lines have that template; first_seen is the index in lines of the first line with that template.count descending, then by first_seen ascending — never alphabetically."" and is grouped like any other. An empty lines list returns [].Worked example
Take ["retry 3 of 5", "job 17 started", "retry 4 of 5", "job 18 started", "retry 1 of 5", "disk full"]. Compute each line's template and use it as a dict key: index 0 gives retry <n> of <n> (new: first_seen 0, count 1), index 1 gives job <n> started (new: first_seen 1), index 2 is retry <n> of <n> again (count 2), index 3 bumps job <n> started to 2, index 4 bumps retry to 3, and index 5 disk full is new at 5. Sorted by count then first_seen: retry 3 at 0, job 2 at 1, disk full 1 at 5.
The trap: grouping by the raw line. "retry 3 of 5" and "retry 4 of 5" are different strings, so every line becomes its own group of 1 and the report hides exactly the repetition the engineer was looking for.
What this tests
Hashing by a normalised key: the pattern behind LeetCode 'Group Anagrams', where the key is a canonical form of the record rather than the record itself. The target is O(total characters) — one pass computing keys into a dict — against the O(n²) habit of comparing each line with every group. A data engineer meets it for real clustering logs and alerts, and deduplicating near-identical records. The shape is reported in data engineering loops: 'Group Anagrams' is tagged for data engineers at Google, Oracle, Goldman Sachs and Visa on Exponent.
group_by_template(lines: list[str]) -> list[dict]Submit for review to find out what your query gets right, what it gets wrong, and how it compares with the best working query for this exercise.
This scenario runs a full workspace — editor, canvas and results side by side. It needs a laptop or desktop to be usable. Open this page on a bigger screen to start building.