Implement solution(user_limit, game_limit, window_ms, requests) to simulate a rate limiter with two independent sliding-window checks.
Each request is a tuple (user_id, game_id, timestamp_ms). A request at time t is allowed only if both conditions hold:
1. The user has fewer than user_limit previously allowed requests with timestamps in [t - window_ms + 1, t].
2. The game has fewer than game_limit previously allowed requests with timestamps in [t - window_ms + 1, t].
If either check fails, reject the request. Rejected requests must not be recorded in either limiter.
Return a list of booleans indicating whether each request is allowed.
Requests are processed in the given order. If multiple requests have the same timestamp, earlier ones in the list are processed first and can affect later ones.
Examples
Input: (2, 1, 100, [('u1', 'g1', 0), ('u2', 'g1', 10), ('u1', 'g2', 20), ('u3', 'g1', 50), ('u1', 'g1', 101)])
Expected Output: [True, False, True, False, True]
Explanation: Game g1 allows only 1 request per 100 ms window, so the requests at 10 and 50 are rejected because g1 already accepted the request at 0. By time 101, timestamp 0 has expired, so the last request is allowed.
Input: (1, 1, 10, [('u1', 'g1', 1), ('u2', 'g1', 2), ('u2', 'g2', 3), ('u2', 'g2', 4), ('u1', 'g2', 11)])
Expected Output: [True, False, True, False, False]
Explanation: The second request is rejected by the game limiter and must not count against user u2. That is why u2 can still be accepted at time 3 on a different game.
Input: (1, 2, 5, [('a', 'x', 0), ('a', 'y', 4), ('a', 'x', 5), ('b', 'x', 5), ('a', 'x', 9)])
Expected Output: [True, False, True, True, False]
Explanation: At time 5, the request at time 0 has expired because the active window is [1, 5]. Later, at time 9, user a already has an accepted request at 5 in the window [5, 9], so the request is rejected.
Input: (3, 3, 50, [])
Expected Output: []
Explanation: Edge case: no requests.