Implement an expiring GPU credits ledger
Company: OpenAI
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Overview: This question evaluates understanding of time-based resource accounting, design of data structures for expiring balances, atomic update semantics for concurrent operations, and algorithmic time/space complexity within the Coding & Algorithms domain.
Read the full OpenAI Software Engineer interview experience this question came from
Constraints
- 1 <= len(operations) <= 20000
- 0 <= amount <= 10^9
- 0 <= expiry_time, timestamp <= 10^9
- Operations are processed in the given order
- A lot is usable exactly when timestamp < expiry_time
Examples
Input: ([('add', 'u1', 50, 10), ('balance', 'u1', 5), ('subtract', 'u1', 20, 6), ('balance', 'u1', 6)],)
Expected Output: [(50, [(50, 10)]), True, (30, [(30, 10)])]
Explanation: At time 5, the lot is still valid, so the balance is 50. Subtracting 20 at time 6 succeeds, leaving 30 in the same lot.
Input: ([('add', 'alice', 10, 5), ('add', 'alice', 30, 20), ('subtract', 'alice', 10, 5), ('balance', 'alice', 5)],)
Expected Output: [True, (20, [(20, 20)])]
Explanation: A lot is valid only when `timestamp < expiry_time`, so the lot expiring at 5 is already invalid at time 5. The subtraction uses the 30-credit lot expiring at 20, leaving 20.
Hints
- Store each user's credits as separate lots instead of merging everything into one number, because expiry times matter during subtraction.
- For atomic subtraction, first compute whether enough unexpired balance exists before changing any lot.