Cloud usage bill from regional hourly rates
You are writing the billing step for a cloud platform. A customer's usage report says which region they ran in and how many hours they used each service. A pricing table gives the hourly rate of every service in every region. Compute what the customer owes.
Implement:
def usage_cost(usage_report, pricing_table) -> dict:
...
Each argument is either a parsed JSON object (a dict) or a JSON string.
// usage_report
{
"region": "eu-west-1",
"usage": [
{"service": "vm", "hours": 10},
{"service": "db", "hours": 3.5},
{"service": "vm", "hours": 2.25}
]
}
// pricing_table: region -> service -> hourly rate
{
"eu-west-1": {"vm": "0.12", "db": 0.5},
"ap-south-1": {"vm": "0.10"}
}
Return {"total": "<amount>", "by_service": {"<service>": "<amount>", ...}}. Write amounts as strings with exactly two decimal places.
Part 1: flat hourly rates
- A service can appear on several usage lines. Add its hours together.
- Hours and rates can be integers, decimal numbers, or numeric strings. Hours can be fractional and are billed exactly.
- Money must be exact. Do not do the arithmetic in binary floating point. Round each service's cost half up to the cent, once. The total is the sum of the rounded service lines.
- Raise
ValueErrorif the region has no prices, a service has no price in that region, or hours are negative or not a number.
Part 2: graduated tiers
A service's price can also be a list of tiers in increasing order, for example:
"egress": [{"up_to": 100, "rate": "0.09"}, {"up_to": null, "rate": "0.05"}]
The first 100 hours of that service, in total across all its usage lines, cost 0.09 each. Every hour after that costs 0.05. up_to: null means no upper limit. If the tiers end with a finite up_to and the usage is larger, raise ValueError.
Constraints
- Up to 10^6 usage lines and 10^3 services per region.
Examples
For the report and table above:
{"total": "3.22", "by_service": {"db": "1.75", "vm": "1.47"}}
vm is 12.25 hours x 0.12 = 1.47. db is 3.5 hours x 0.5 = 1.75.
With the egress tiers above added to eu-west-1, a report with two egress lines of 60 and 90 hours costs 100 x 0.09 + 50 x 0.05:
{"total": "11.50", "by_service": {"egress": "11.50"}}
Reconstructed from the reported question; details may differ from what interviewers ask.
Sign in to see the worked answer
The full answer, chapter by chapter, with what interviewers expect at each level. Free with an account: one full answer per company.
