it‑training
1400

Ограничитель запросов

designsliding-windowtbankyandex
python35000 мс512 МБcpp202000 мс256 МБ

Реализуйте ограничитель частоты запросов со скользящим окном в одну секунду.

Время в задаче виртуальное: оно не идёт само, а сдвигается только вызовами tick.

Интерфейс

RateLimiter(rps)          создать ограничитель: не более rps запросов
                          на каждый ключ за любое окно в 1000 мс
allow(key) -> bool        запрос по ключу key в текущий момент времени.
                          Вернуть true, если запрос разрешён (и учесть его),
                          иначе false — отклонённый запрос не учитывается
tick(ms) -> void          сдвинуть текущее время вперёд на ms миллисекунд

Начальное время — 0. Ограничение считается по скользящему окну: запрос разрешён, если за последние 1000 мс, включая текущий момент, по этому ключу было разрешено менее rps запросов.

Ограничения

  • $1 \le rps \le 1000$
  • не более $100000$ операций
  • ключи — непустые строки латинских букв и цифр

Замечание

Окно скользящее, а не фиксированное. Реализация, обнуляющая счётчик каждую секунду, пропустит вдвое больше запросов на границе окна и не будет принята.

Интерфейс

class RateLimiter
  RateLimiter(rps: int)
  allow(key: string) -> bool
  tick(ms: long) -> void

Реализуйте класс с этой сигнатурой. Ввод и вывод обрабатывать не нужно — решение вызывается напрямую.

Примеры

операции
[["RateLimiter", 2], ["allow", "a"], ["allow", "a"], ["allow", "a"], ["tick", 1000], ["allow", "a"]]
результаты
[null, true, true, false, null, true]
операции
[["RateLimiter", 2], ["tick", 900], ["allow", "a"], ["allow", "a"], ["tick", 100], ["allow", "a"], ["allow", "b"]]
результаты
[null, null, true, true, null, false, true]
Ctrl
Нет запуска
Ввод
[["RateLimiter", 2], ["allow", "a"], ["allow", "a"], ["allow", "a"], ["tick", 1000], ["allow", "a"]]
Ожидалось
[null, true, true, false, null, true]