Debug a driver assignment bug
Company: DoorDash
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Onsite
Quick Answer: This question evaluates debugging, root-cause analysis, unit/integration test design, observability, and system-resilience competencies within the Coding & Algorithms domain, emphasizing practical skills in reproducing failures, isolating defects, and implementing targeted fixes.
Constraints
- 0 <= len(dashers) <= 200000
- Each dasher is a tuple: (driver_id, distance_meters, last_update_ms, available)
- distance_meters and last_update_ms may be None; such dashers must be ignored
- 0 <= stale_after_seconds <= 10^6
- 0 <= jitter_tolerance_m <= 10^6
Examples
Input: ([(1, 100, 80000, True), (2, 120, 98000, True)], 100000, 30, 5)
Expected Output: 1
Explanation: Dasher 1 is only 20 seconds old, so it is still fresh. The old bug would incorrectly treat 30 seconds as 30 milliseconds. The correct answer is driver 1 because it is clearly closer than driver 2.
Input: ([], 100000, 30, 5)
Expected Output: -1
Explanation: There are no candidates, so no assignment can be made.
Input: ([(10, 100, 90000, True), (2, 103, 95000, True)], 100000, 30, 5)
Expected Output: 2
Explanation: The minimum distance is 100, and with 5 meters of jitter tolerance both drivers are considered equally close. Driver 2 has the more recent location update, so it wins.
Input: ([(7, 100, 95000, True), (3, 100, 95000, True)], 100000, 30, 0)
Expected Output: 3
Explanation: Both drivers have identical distance and identical freshness, so the smaller driver_id wins.
Input: ([(1, None, 99000, True), (2, 80, None, True), (3, 90, 99000, False)], 100000, 30, 5)
Expected Output: -1
Explanation: The first driver has missing distance, the second has a missing timestamp, and the third is unavailable. No valid driver remains.
Input: ([(1, 50, 70000, True), (2, 40, 69999, True)], 100000, 30, 0)
Expected Output: 1
Explanation: Driver 1 is exactly 30 seconds old, which is still valid. Driver 2 is 30001 milliseconds old and is stale, so only driver 1 can be selected.
Input: ([(5, 70, 101000, True), (4, 68, 50000, True)], 100000, 30, 3)
Expected Output: 5
Explanation: Driver 5 has a future timestamp due to clock skew, so its age is treated as 0. Driver 4 is stale. Therefore driver 5 is selected.
Solution
def solution(dashers, current_time_ms, stale_after_seconds, jitter_tolerance_m):
stale_limit_ms = stale_after_seconds * 1000
def is_valid(dasher):
if not isinstance(dasher, (list, tuple)) or len(dasher) != 4:
return False
driver_id, distance_meters, last_update_ms, available = dasher
if not available:
return False
if distance_meters is None or last_update_ms is None:
return False
if distance_meters < 0:
return False
age = current_time_ms - last_update_ms
if age < 0:
age = 0
return age <= stale_limit_ms
min_distance = None
for dasher in dashers:
if is_valid(dasher):
distance_meters = dasher[1]
if min_distance is None or distance_meters < min_distance:
min_distance = distance_meters
if min_distance is None:
return -1
threshold = min_distance + jitter_tolerance_m
best_id = None
best_update = None
for dasher in dashers:
if not is_valid(dasher):
continue
driver_id, distance_meters, last_update_ms, _ = dasher
if distance_meters <= threshold:
if best_id is None:
best_id = driver_id
best_update = last_update_ms
elif last_update_ms > best_update:
best_id = driver_id
best_update = last_update_ms
elif last_update_ms == best_update and driver_id < best_id:
best_id = driver_id
best_update = last_update_ms
return best_id if best_id is not None else -1Time complexity: O(n). Space complexity: O(1).
Hints
- Be very careful with time units: current_time_ms and last_update_ms are milliseconds, but stale_after_seconds is in seconds.
- You do not need to sort the whole list. First find the minimum valid distance, then scan again to apply the tie-break rules.