Multi-Level Warehouse Storage with Weighted Retrieval
Company: Ramp
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Take-home Project
Quick Answer: This question evaluates a candidate's ability to design an object-oriented data structure with multiple prioritized eviction and expiration rules. It tests skills in coding and algorithms, specifically simulating TTL-based expiry alongside tiered, capacity-aware selection logic. Such multi-rule state machine problems are common in interviews to assess careful requirement tracking and practical implementation of layered constraints.
Constraints
- num_levels >= 1, capacity >= 1, ttl >= 1
- All weight, timestamp, and ttl values are non-negative integers; weight may repeat across items
- timestamp values are non-decreasing across successive calls
- Each item_id passed to store is unique across the object's lifetime
- An item stored at t is valid for query q while q < t + ttl; expired once q >= t + ttl
- A level is a retrieval candidate iff it holds >= ceil(capacity / 2) valid items
Examples
Input: (['Storage', 'store', 'store', 'store', 'retrieve', 'retrieve', 'retrieve', 'retrieve'], [[2, 2, 10], [1, 5, 0], [2, 8, 0], [3, 3, 1], [2], [2], [2], [2]])
Expected Output: [None, 0, 0, 1, 2, 1, 3, None]
Explanation: Main example from the prompt.
Input: (['Storage', 'store', 'retrieve'], [[1, 1, 10], [1, 5, 0], [10]])
Expected Output: [None, 0, None]
Explanation: Item stored at t=0 is expired at t=10 (10 >= 0+10), so retrieve returns None.
Input: (['Storage', 'store', 'retrieve'], [[1, 1, 10], [1, 5, 0], [9]])
Expected Output: [None, 0, 1]
Explanation: Boundary: item still valid at t=9 (9 < 0+10); level has 1 item >= ceil(1/2)=1.
Input: (['Storage', 'store', 'store'], [[1, 1, 10], [1, 5, 0], [2, 6, 0]])
Expected Output: [None, 0, -1]
Explanation: Single-slot level is full of non-expired items, so the second store returns -1.
Input: (['Storage', 'store', 'store', 'retrieve', 'retrieve'], [[1, 2, 100], [5, 7, 0], [2, 7, 0], [1], [1]])
Expected Output: [None, 0, 0, 2, 5]
Explanation: Equal weights (7); tie broken by smallest item_id -> item 2 first, then item 5.
Input: (['Storage', 'store', 'retrieve', 'store', 'retrieve'], [[1, 4, 100], [1, 5, 0], [0], [2, 6, 0], [0]])
Expected Output: [None, 0, None, 0, 2]
Explanation: capacity=4 needs ceil(4/2)=2 valid items to be a candidate; 1 item -> None, 2 items -> highest weight (item 2).
Input: (['Storage', 'store', 'store', 'store'], [[2, 1, 5], [1, 5, 0], [2, 6, 1], [3, 7, 5]])
Expected Output: [None, 0, 1, 0]
Explanation: Expiry frees the top slot: item 1 (t=0) is expired at t=5, so item 3 lands back on level 0 instead of level 1.
Input: (['Storage', 'retrieve'], [[3, 2, 10], [0]])
Expected Output: [None, None]
Explanation: Retrieve on a freshly initialized empty warehouse returns None.
Hints
- Track each item as (item_id, weight, timestamp) grouped per level. Expiration is lazy: only prune a level when you touch it (during store's free-slot count and at the start of retrieve).
- store scans levels from index 0 upward; place on the first level whose non-expired count is below capacity, else return -1.
- retrieve first expires everything, then finds the topmost level with >= ceil(capacity/2) = (capacity + 1) // 2 valid items, then selects max weight with smallest item_id as the tie-breaker.
- Level order dominates: a lower-index candidate always wins over a heavier item sitting on a level below it.