Presale Search Cap

EasydesignAlso known as Fixed Window Rate Limiter

When concert presale opens, fans hammer the seat search, and a few scripts refresh it hundreds of times a minute. The ticket site caps each fan at a few searches per clock minute: the counter for 10:04 starts at zero at 10:04:00 and is thrown away at 10:05:00. Over the cap, the fan gets an HTTP 429 "Too Many Requests" instead of results.

This is the fixed-window counter from Rate Limiting: one small counter per user per window, cheap enough to keep for millions of users in a shared in-memory store. Its known flaw shows up at the window edge, which the examples below make visible.

Your task

Write a class WindowLimiter:

  • constructor(limit, windowSec): each fan may make at most limit allowed requests per window.
  • allow(fan, t): a request from fan at time t (whole seconds). Return true if it is allowed, false if it is rejected.

Windows are fixed and aligned to 0: a request at time t falls in window number floor(t / windowSec), so with windowSec = 60 the windows are [0, 59], [60, 119], and so on. A request is allowed if the fan has had fewer than limit allowed requests in the same window. Rejected requests do not count. Each fan has separate counts.

class WindowLimiter

Examples

Example 1
Input
new WindowLimiter(3, 60)
.allow("ana", 10)
.allow("ana", 20)
.allow("ana", 30)
.allow("ana", 59)
.allow("ana", 60)
Output
[null, true, true, true, false, true]
Why

Times 10, 20, 30 and 59 are all in window 0 (0 to 59). The first three are allowed, which uses up the limit of 3, so the request at 59 is rejected. Time 60 starts window 1 with a fresh count, so it is allowed.

Example 2
Input
new WindowLimiter(2, 60)
.allow("ben", 58)
.allow("ben", 59)
.allow("cy", 59)
.allow("ben", 60)
.allow("ben", 61)
Output
[null, true, true, true, true, true]
Why

Ben gets 2 requests at 58 and 59 in window 0, then 2 more at 60 and 61 in window 1: 4 requests in 4 seconds, although the limit is 2 per minute. That burst at the edge is the price of fixed windows. Cy has her own count, so her request at 59 is allowed even though Ben used up his.

Constraints

  • 1 ≤ limit ≤ 1,000
  • 1 ≤ windowSec ≤ 86,400
  • 0 ≤ t ≤ 1,000,000,000, and t never decreases from one call to the next
  • fan is a non-empty string of up to 20 letters and digits
  • At most 2,000 calls per test
Start with brute force

Store every allowed request time for each fan, and on each new request count how many stored times fall in the same window. With 2,000 calls that is up to 2,000 × 2,000 = 4 million checks, and the stored history grows forever.

Since only the current window can matter, a single counter per fan is enough, and both time and memory per fan become constant.

Hints

0 of 4 shown

Walkthrough and solution

Unlocks when you pass every test. Stuck for a while? Looking is fine too, as long as you then close it and write the code yourself.

Ctrl+Enter runs

Run your code to see results here. Run checks the examples. Submit checks every test, including hidden edge cases.

Write code