Implement Courier Delivery Cost Tracking
RipplingSoftware Engineer · Technical ScreenLast updated
Design an in-memory billing system that tracks courier pay rates over time and calculates prorated delivery costs across half-open time intervals.
Problem Statement
You are tasked with building a billing tracker for an on-demand courier platform. Couriers are paid based on hourly rates that can change over time. Each delivery is logged as a half-open time interval [start_time, end_time) in seconds.
Implement the CourierDeliveryTracker class with the following methods:
-
set_rate(courier_id: str, timestamp: int, hourly_rate_cents: int) -> NoneSets the courier's hourly rate (in cents) starting fromtimestamp(inclusive). This rate remains in effect until a later rate is set for that courier. Timestamps for a given courier may not necessarily arrive in chronological order. -
record_delivery(delivery_id: str, courier_id: str, start_time: int, end_time: int) -> NoneRecords a delivery completed bycourier_idduring[start_time, end_time)wherestart_time intCalculates the total cost (in cents) for the specified delivery. If the delivery spans multiple rate periods, prorate the pay according to the time spent in each rate period. The exact prorated cost fordseconds at ratercents/hour isd * r / 3600. Sum all unrounded segment costs, then round half up to the nearest cent:math.floor(total + 0.5). -
get_courier_payout(courier_id: str, start_time: int, end_time: int) -> intReturns the total earnings forcourier_idacross all deliveries that overlap with the query window[start_time, end_time). For deliveries that only partially overlap with the query window, only count the overlapping portion. Deliveries for a single courier do not overlap with each other.
Example
tracker = CourierDeliveryTracker()
# Courier C1 starts at $18.00/hr (1800 cents/hr) at t = 0
tracker.set_rate("C1", 0, 1800)
# Courier C1 gets a raise to $24.00/hr (2400 cents/hr) at t = 3600
tracker.set_rate("C1", 3600, 2400)
# Delivery D1 spans t = 1800 to t = 5400 (1 hour under 1800, 0.5 hours under 2400)
tracker.record_delivery("D1", "C1", 1800, 5400)
# Cost: (1800s * 1800 / 3600) + (1800s * 2400 / 3600) = 900 + 1200 = 2100 cents
print(tracker.get_delivery_cost("D1")) # Output: 2100
# Payout for window [3600, 7200)
# Overlap with D1 is [3600, 5400) (1800s at 2400 cents/hr = 1200 cents)
print(tracker.get_courier_payout("C1", 3600, 7200)) # Output: 1200
Constraints
- Timestamps are non-negative integers:
0 = 0 - For every delivery,
start_time >= min(timestamp)among all rate changes for that courier. - Up to
10^4calls across all methods. - Each
delivery_idis unique.
Hints
Hint 1
Maintain each courier's rate history as a sorted list of (timestamp, rate) tuples to enable binary search (bisect) for any given point in time.
Hint 2
To calculate cost across an interval [start, end), find all sub-intervals created by rate change timestamps that fall within [start, end) and compute the duration of each slice.
Hint 3
For get_courier_payout, intersect each courier's deliveries with the requested [start_time, end_time) window before evaluating the cost of each overlapping slice.
Follow-up questions
- How would you optimize `get_courier_payout` if there are millions of historical deliveries per courier?
- How would your interval intersection logic change if couriers could fulfill multiple overlapping deliveries concurrently (e.g., pooled deliveries)?
- How would you handle non-linear billing rules, such as overtime pay kicking in after 8 hours in a rolling 24-hour window?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.