The Event Window
A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- medium
- Seniority
- L4
- Asked in
- Citadel
Problem
A request-tracking service for an API needs to answer one question on demand: how many hits landed in the last five minutes. Implement a HitCounter whose hit(timestamp) records an event at the given second and whose get_hits(timestamp) returns how many recorded events fall inside the trailing 300-second window ending at and including timestamp, so a hit at exactly timestamp - 300 has already aged out. Timestamps arrive in non-decreasing order.
Then implement the graded entrypoint event_window(operations, arguments): given a list of operation names ("HitCounter", "hit", "get_hits") and a parallel list of argument lists, replay them against a single counter and return one result per operation, None for "HitCounter" and "hit" and the integer count for each "get_hits".
A five-minute window is all that matters.
Example
Input:
arguments = [[],[1],[2],[3],[4],[300],[300],[301]], operations = ["HitCounter","hit","hit","hit","get_hits","hit","get_hits","get_hits"]
Output:
[null,null,null,null,3,null,4,3]
Worked solution and explanation
What this really is
Strip the costume and this is a rolling-window count over a sorted event stream: hold the timestamps you have seen, and on each query report how many still fall inside the trailing 300 seconds. Anyone can store every hit and re-scan the whole list per query. What separates a strong candidate is noticing the stream is non-decreasing, so once a timestamp leaves the window it never returns, and you can drop it for good from the front. Get the boundary wrong and you count a hit that aged out exactly 300 seconds ago, or evict one that is still alive.
Break down the requirements
Step 1: Record timestamps on hit
Store each hit timestamp in an ordered structure (a deque) as it arrives.
Step 2: Query hits within the last 300 seconds
Count all stored timestamps h that satisfy timestamp - 300 < h <= timestamp, i.e. those within the trailing 300-second window ending inclusively at timestamp.
Step 3: Optimize for repeated queries
Lazily discard expired timestamps from the front of the queue on each query, so each timestamp is added and removed at most once.
Step 4: Expose a replay driver
Wrap the class in a driver event_window(operations, arguments) that replays the op sequence against one instance and collects the results, since the grader calls a single top-level function.
The solution
from collections import deque
class HitCounter:
def __init__(self):
self.hits = deque()
def hit(self, timestamp: int):
self.hits.append(timestamp)
def get_hits(self, timestamp: int) -> int:
cutoff = timestamp - 299
while self.hits and self.hits[0] < cutoff:
self.hits.popleft()
return len(self.hits)
def event_window(operations, arguments):
counter = None
results = []
for op, args in zip(operations, arguments):
if op == "HitCounter":
counter = HitCounter()
results.append(None)
elif op == "hit":
counter.hit(*args)
results.append(None)
elif op == "get_hits":
results.append(counter.get_hits(*args))
return resultsCommon follow-up questions
- What if timestamps can arrive out of order? (Tests maintaining sorted order or using a different data structure.)
- How would you support configurable window sizes? (Tests parameterizing the 300-second constant.)
- What if you need the hit rate (hits per second)? (Tests dividing count by window size.)
- How would you handle millions of hits per second? (Tests bucket-based counting (one counter per second) instead of storing individual timestamps.)