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 enrichment step looks each row's key up in a dimension that costs real money per call. The stream repeats keys constantly, and the obvious loop pays for every repeat.
Write resolve_lookups(keys, source, cache_size). It returns the resolved values and how many times the source was actually consulted.
Function to write
resolve_lookups(keys: list, source: dict, cache_size: int) -> dictA dict with the `results` in input order and the number of `source_calls` made.
How to approach it
Count the source calls first, then make the number go down.
Sample cases
+ 2 held back until you submit
a repeated key and a miss
Four lookups, three distinct keys, three source calls — and the unknown key resolves to None.
Input
Argument 1
[
'u1',
'u1',
'u2',
'u3'
]Argument 2
{
'u1': 'Amir',
'u2': 'Cara'
}Argument 3
128Returns
{
'results': [
'Amir',
'Amir',
'Cara',
None
],
'source_calls': 3
}caching turned off
A cache size of zero is a real setting: every lookup reaches the source.
Input
Argument 1
[
'u1',
'u1'
]Argument 2
{
'u1': 'Amir',
'u2': 'Cara'
}Argument 3
0Returns
{
'results': [
'Amir',
'Amir'
],
'source_calls': 2
}nothing to resolve
No keys means no results and no source calls, rather than a division or an index error.
Input
Argument 1
[] (empty list)
Argument 2
{
'u1': 'Amir',
'u2': 'Cara'
}Argument 3
128Returns
{
'results': [],
'source_calls': 0
}Constraints
{'results': [...], 'source_calls': <count>}, with one result per key in input order.None, and that is a result — asking again would be a second call for the same answer.cache_size of 0 disables caching entirely. It is a real setting, not an error: it is how somebody measures what the cache is worth.Worked example
Resolve u1, u1, u2, u3 with a large cache. Four results come back — Amir, Amir, Cara, None — from three source calls.
The u3 case is the one worth thinking about. It is not in the source, so the answer is None; caching that None is the difference between one wasted call and one per occurrence, and a cache that only stores successes is a cache that does nothing at all for a stream of unknown keys.
What this tests
That memoisation is a decorator over a function rather than a dict scattered through a loop, that the cache size is a real trade rather than a constant, and that the cost of a lookup is measured rather than assumed.
resolve_lookups(keys: list, source: dict, cache_size: int) -> dictSubmit 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.