Problem 639463 · easy · Level 06 Heuristics & Optimization

Ask Every Source at Once

py-async · coroutines · await · gather · error handling

A weather dashboard shows one reading from each of its sources. Each source answers after a delay, and some sources are offline. Asking them one after another makes the dashboard as slow as all the delays added together; asking them all at once makes it as slow as the slowest one.

Write a coroutine function dashboard(names) that asks every source at the same time and returns a list with one line per source, in the order of names: "name: reading" for a source that answered, and "name: offline" for one whose fetch raised ConnectionError.

The browser already runs an event loop of its own, so on this site the tests run your coroutines on a small loop with a virtual clock (no real waiting, no asyncio.run). The setup gives you the tools, which work like their asyncio namesakes:

  • await fetch(name): ask one source; it takes that source's delay in ticks and returns the reading, or raises ConnectionError.
  • await gather(*coroutines): run several coroutines at the same time and return their results, in the order given (an exception in one of them is raised by gather).
  • await pause(ticks) (like asyncio.sleep), spawn(coroutine) (like asyncio.create_task) and now() (the current tick).

refresh(dashboard, sources) runs your dashboard for a list of (name, delay, reading) sources (reading is None when the source is offline) and returns (your result, the tick at which it finished). city_sources(n, seed) generates sources.

Examples

Input:  refresh(dashboard, [("roof", 3, 21.5), ("garden", 7, None), ("cellar", 5, 12.0)])
Output: (["roof: 21.5", "garden: offline", "cellar: 12.0"], 7)
Explanation: all three are asked at tick 0; the slowest takes 7 ticks. One after another would take 15.

Input:  refresh(dashboard, [])
Output: ([], 0)

Constraints

  • Up to 500 sources, delays from 0 to 100 ticks.
  • Do not call asyncio.run or asyncio.sleep; the virtual clock only moves with pause and fetch.

Goals

  • Write coroutine functions with `async def` and `await`
  • Start several waits at the same time and collect their results in the order asked for
  • Handle a failing source inside its own coroutine, so the others are not affected
Starting Python…