Implement Food Delivery Billing
Company: Rippling
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Onsite
Quick Answer: This question evaluates proficiency in implementing business billing rules, time and distance-based fee calculations, timestamp arithmetic, numerical rounding, and efficient aggregation for payouts; it falls under the Coding & Algorithms domain with emphasis on billing logic, time-series aggregation, and data processing.
Part 1: Compute Customer Delivery Charge for One Order
Constraints
- All timestamps use the format 'YYYY-MM-DD HH:MM' and are in the same timezone.
- 0 <= distance_km <= 1000
- requested_at <= picked_up_at <= delivered_at
- All timestamps are exact to the minute.
Examples
Input: ({'requested_at': '2024-05-01 10:30', 'picked_up_at': '2024-05-01 10:40', 'delivered_at': '2024-05-01 11:00', 'distance_km': 5.0},)
Expected Output: 13.0
Explanation: Base 2.00 + distance 6.00 + time 5.00 = 13.00. Requested time is not peak.
Input: ({'requested_at': '2024-05-01 11:15', 'picked_up_at': '2024-05-01 11:20', 'delivered_at': '2024-05-01 11:50', 'distance_km': 3.5},)
Expected Output: 20.55
Explanation: Before multiplier: 2.00 + 4.20 + 7.50 = 13.70. Lunch peak applies, so 13.70 * 1.5 = 20.55.
Input: ({'requested_at': '2024-05-01 13:00', 'picked_up_at': '2024-05-01 13:05', 'delivered_at': '2024-05-01 13:25', 'distance_km': 2.0},)
Expected Output: 9.4
Explanation: 13:00 is outside the peak window because the end is exclusive. Total = 2.00 + 2.40 + 5.00 = 9.40.
Input: ({'requested_at': '2024-05-01 18:00', 'picked_up_at': '2024-05-01 18:10', 'delivered_at': '2024-05-01 18:10', 'distance_km': 0.0},)
Expected Output: 3.0
Explanation: Zero distance and zero delivery time. Base fee 2.00 gets multiplied by peak factor 1.5, giving 3.00.
Hints
- First compute the delivery duration in minutes using picked_up_at and delivered_at.
- Check the peak-hour multiplier using only requested_at, not pickup or delivery time.
Part 2: Total Driver Payout Owed Up to a Timestamp
Constraints
- 0 <= len(deliveries) <= 100000
- All timestamps use the format 'YYYY-MM-DD HH:MM' and are in the same timezone.
- For every delivery, picked_up_at <= delivered_at.
- All timestamps are exact to the minute.
Examples
Input: ('2024-05-01 12:00', [{'picked_up_at': '2024-05-01 10:00', 'delivered_at': '2024-05-01 10:20', 'distance_km': 5.0}, {'picked_up_at': '2024-05-01 11:00', 'delivered_at': '2024-05-01 12:00', 'distance_km': 2.5}, {'picked_up_at': '2024-05-01 12:05', 'delivered_at': '2024-05-01 12:30', 'distance_km': 1.0}])
Expected Output: 28.0
Explanation: The first two deliveries are payable by 12:00. Their payouts are 11.00 and 17.00, for a total of 28.00.
Input: ('2024-05-01 18:45', [{'picked_up_at': '2024-05-01 18:00', 'delivered_at': '2024-05-01 18:45', 'distance_km': 4.0}])
Expected Output: 15.2
Explanation: Equality counts. Payout = 3.00 + 3.20 + 9.00 = 15.20.
Input: ('2024-05-01 09:00', [])
Expected Output: 0.0
Explanation: No deliveries means nothing is owed.
Input: ('2024-05-01 09:00', [{'picked_up_at': '2024-05-01 10:00', 'delivered_at': '2024-05-01 10:10', 'distance_km': 1.0}, {'picked_up_at': '2024-05-01 11:00', 'delivered_at': '2024-05-01 11:30', 'distance_km': 3.0}])
Expected Output: 0.0
Explanation: The query time is before all delivered_at values, so no delivery is payable yet.
Hints
- A delivery contributes to the answer only if its delivered_at is less than or equal to the query timestamp.
- Compute the payout for each eligible delivery independently, then add them up.
Part 3: Efficiently Answer Many Driver Payout Queries
Constraints
- 0 <= len(deliveries) <= 200000
- 0 <= len(query_timestamps) <= 200000
- All timestamps use the format 'YYYY-MM-DD HH:MM' and are in the same timezone.
- For every delivery, picked_up_at <= delivered_at.
- All timestamps are exact to the minute.
Examples
Input: ([{'picked_up_at': '2024-05-01 10:00', 'delivered_at': '2024-05-01 10:20', 'distance_km': 5.0}, {'picked_up_at': '2024-05-01 11:00', 'delivered_at': '2024-05-01 11:15', 'distance_km': 1.5}, {'picked_up_at': '2024-05-01 12:00', 'delivered_at': '2024-05-01 12:40', 'distance_km': 3.0}], ['2024-05-01 11:00', '2024-05-01 12:40', '2024-05-01 09:59', '2024-05-01 11:15'])
Expected Output: [11.0, 31.6, 0.0, 18.2]
Explanation: The answers must follow the query order, not sorted order.
Input: ([{'picked_up_at': '2024-05-01 18:00', 'delivered_at': '2024-05-01 18:30', 'distance_km': 2.0}, {'picked_up_at': '2024-05-01 18:10', 'delivered_at': '2024-05-01 18:30', 'distance_km': 1.0}], ['2024-05-01 18:29', '2024-05-01 18:30', '2024-05-01 18:31'])
Expected Output: [0.0, 18.4, 18.4]
Explanation: Multiple deliveries can share the same delivered_at time. They all become payable at that timestamp.
Input: ([], ['2024-05-01 10:00', '2024-05-01 12:00'])
Expected Output: [0.0, 0.0]
Explanation: With no deliveries, every query returns 0.00.
Input: ([{'picked_up_at': '2024-05-01 10:00', 'delivered_at': '2024-05-01 10:10', 'distance_km': 1.0}], [])
Expected Output: []
Explanation: No queries means no results.
Hints
- Sort deliveries by delivered_at, then build a prefix-sum array of cumulative payouts.
- For each query timestamp, use binary search to find how many deliveries are payable by that time.