Design streaming test logger and queries
Company: Vanta
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates a candidate's ability to design streaming data structures and time-series algorithms to track state transitions and compute interval queries, covering competencies in online/event-processing algorithms, interval overlap aggregation, and algorithmic complexity analysis within the Coding & Algorithms domain.
Part 1: Build normalized failure intervals from log()
Constraints
- 0 <= len(logs) <= 200000
- Each log entry is `(test_id, timestamp, status)`
- Timestamps are integers and strictly increasing across the entire stream
- status is always either 'failing' or 'passing'
Examples
Input: ([('T1', 1, 'failing'), ('T1', 4, 'passing')],)
Expected Output: {'T1': [(1, 4)]}
Explanation: A single failing streak starts at 1 and resolves at 4.
Input: ([('T1', 1, 'failing'), ('T1', 2, 'failing'), ('T1', 5, 'passing'), ('T1', 8, 'failing')],)
Expected Output: {'T1': [(1, 5), (8, None)]}
Explanation: The first two failing logs are one streak. The final failure is unresolved.
Hints
- Track, for each test, whether a failure is currently open and when it started.
- A 'failing' log only matters if the test was not already failing; a 'passing' log only matters if it was.
Part 2: Minimum fix time for one test
Constraints
- 0 <= len(logs) <= 200000
- Each log entry is `(test_id, timestamp, status)`
- Timestamps are integers and strictly increasing across the entire stream
- status is always either 'failing' or 'passing'
Examples
Input: ([('A', 1, 'failing'), ('A', 3, 'passing'), ('A', 5, 'failing'), ('A', 9, 'passing')], 'A')
Expected Output: 2
Explanation: Resolved failure lengths are 2 and 4, so the minimum is 2.
Input: ([('A', 1, 'failing'), ('B', 2, 'failing'), ('A', 4, 'failing'), ('A', 6, 'passing'), ('B', 8, 'passing'), ('A', 10, 'failing'), ('A', 12, 'passing')], 'A')
Expected Output: 2
Explanation: For A, the streak from 1 to 6 has length 5 because the extra failing at 4 does not restart it. The second resolved streak has length 2.
Hints
- You only need to track the current open failure for the queried test, not for every test.
- Ignore consecutive 'failing' logs until you see a 'passing' log that closes the active failure.
Part 3: Longest period with at least k concurrent failing tests
Constraints
- 0 <= len(logs) <= 200000
- Each log entry is `(test_id, timestamp, status)`
- Timestamps are integers and strictly increasing across the entire stream
- status is always either 'failing' or 'passing'
- 1 <= min_tests <= 200000
Examples
Input: ([('A', 1, 'failing'), ('B', 2, 'failing'), ('A', 5, 'passing'), ('B', 7, 'passing')], 2)
Expected Output: {'start_timestamp': 2, 'end_timestamp': 5}
Explanation: A fails on [1, 5), B fails on [2, 7), so both are failing together on [2, 5).
Input: ([('A', 1, 'failing'), ('A', 2, 'failing'), ('B', 3, 'failing'), ('C', 4, 'failing'), ('B', 6, 'passing'), ('A', 8, 'passing'), ('C', 10, 'passing')], 2)
Expected Output: {'start_timestamp': 3, 'end_timestamp': 8}
Explanation: At least two tests are failing continuously from 3 to 8. The extra failing log for A at 2 does not create a new interval.
Hints
- The number of failing tests can only change at log timestamps, so scan the stream segment by segment between consecutive timestamps.
- Maintain the current set of failing tests and the start of the current qualifying window where the failing count is at least `min_tests`.