Token Bucket Bouncer
Simulate an API rate limiter that combines a token bucket (for bursts) with a per-minute quota, tracking every client separately.
Statement
Story
A public API is being hammered by scrapers. The team decides on two limits that work together: a token bucket lets a client burst a little but forces a steady average, and a per-minute quota caps the total regardless of how smooth the traffic looks. Before putting it in front of production you simulate it on recorded traffic and print which requests it would have let through.
The rules
Every client (the string identifying it) has its own state, created at its first request.
- Token bucket. The bucket holds at most
capacitytokens and starts full at the client's first request. It refills continuously atrefilltokens per second (sorefill = 2adds one token every 500 ms, and fractions of a token accumulate), never abovecapacity. A request needs at least one whole token. - Fixed-window quota. Time is cut into 60-second windows aligned to time 0: the window of a timestamp
t(milliseconds) isfloor(t / 60000). A client may have at mostwindow_limitallowed requests in each window; a new window starts counting from zero. - A request is allowed only if the bucket has a token and the quota is not used up. Allowed requests take one token and one unit of quota. A denied request takes nothing from either.
The requests arrive in non-decreasing timestamp order across all clients. capacity, refill and window_limit are integers (0 or more), timestamps are integer milliseconds.
Your task
Implement rate_limit(capacity, refill, window_limit, requests) in Python or rateLimit(capacity, refill, windowLimit, requests) in JavaScript. requests is a list of [client, timestamp_ms] pairs. Return a list of booleans, one per request, in order: True when it is allowed.
A test driver calls your function and prints A for every allowed and D for every denied request. Write only the function (and helpers); do not read input or print anything yourself.
Example
capacity = 2, refill = 1, window_limit = 10
requests = [["a", 0], ["a", 0], ["a", 0], ["a", 1000], ["a", 1500], ["b", 1500]]
result = [True, True, False, True, False, True] # printed as AADADA
Client a empties its two tokens at time 0, so the third request is denied. One second later exactly one token is back (allowed), but 500 ms later only half a token is (denied). Client b starts with its own full bucket.
Sample input
[{"capacity":2,"refill":1,"window_limit":10,"requests":[["a",0],["a",0],["a",0],["a",1000],["a",1500],["b",1500]]}]
Allowed languages: python, javascript
Hints
Stuck? Hints are optional, and each one lowers the points you earn for solving this challenge.
- Hint 1Costs 20 points
- Hint 2Costs 30 points
Reveal the previous hint first
- Hint 3Costs 40 points
Reveal the previous hint first
Lessons that teach this
Stuck on the ideas rather than the puzzle? These lessons cover what you need.