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
A load rejected forty thousand rows. Nobody is going to read forty thousand records, so the run reports a summary: which reasons, how many of each, and a few examples to look at.
Write summarise_rejections(rejections, sample_limit). It returns one entry per reason, ordered so the same input always produces the same report.
Function to write
summarise_rejections(rejections: list[dict], sample_limit: int) -> list[dict]A list of per-reason summaries, ordered by count descending then reason ascending.
How to approach it
Run the starter twice and compare the order of the two tied reasons.
Sample cases
+ 2 held back until you submit
three reasons, one of them unnamed
Ordering, the sample cap, and a rejection whose reason nobody set.
Input
Argument 1
[
{
'reason': 'bad amount',
'row': {
'id': 1
}
},
{
'reason': 'bad amount',
'row': {
'id': 2
}
},
{
'reason': 'missing buyer',
'row': {
'id': 3
}
},
{
'row': {
'id': 4
}
}
]Argument 2
1Returns
[
{
'reason': 'bad amount',
'count': 2,
'samples': [
{
'id': 1
}
]
},
{
'reason': 'missing buyer',
'count': 1,
'samples': [
{
'id': 3
}
]
},
{
'reason': 'unknown',
'count': 1,
'samples': [
{
'id': 4
}
]
}
]two reasons with the same count
A tie in the counts is broken by the reason, so the report is the same on every run.
Input
Argument 1
[
{
'reason': 'missing buyer',
'row': {
'id': 1
}
},
{
'reason': 'bad amount',
'row': {
'id': 2
}
}
]Argument 2
5Returns
[
{
'reason': 'bad amount',
'count': 1,
'samples': [
{
'id': 2
}
]
},
{
'reason': 'missing buyer',
'count': 1,
'samples': [
{
'id': 1
}
]
}
]nothing was rejected
A clean run summarises to an empty list, which is the answer rather than an absence.
Input
Argument 1
[] (empty list)
Argument 2
3Returns
[] (empty list)
Constraints
{'reason': ..., 'count': ..., 'samples': [...]}.samples holds up to sample_limit of the row values, in input order.unknown rather than dropped.sample_limit of 0 is a real request: counts, no samples.Worked example
Four rejections arrive: two bad amount, one missing buyer, and one with no reason set at all.
With a sample limit of 1 the report is bad amount (2), then missing buyer (1), then unknown (1) — the last two tie on count and are ordered by name. The unnamed one is the case worth noticing: it is a real rejection, and a summary that quietly drops it makes the counts stop matching the manifest.
What this tests
That a report is a designed artefact — bounded, ordered deterministically, and complete — rather than whatever the grouping happened to produce. The unnamed reason is the case that separates the two.
summarise_rejections(rejections: list[dict], sample_limit: int) -> 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.