Price an order across volume tiers
A wholesaler charges less per unit the more you buy, and the tiers stack: the first slice of the order is charged at the first rate, the next slice at the second, and so on.
- Tiers arrive sorted by upTo, which is a running total, not a slice width.
- A tier covers the units between where the previous tier stopped and its own upTo.
- Anything beyond the last tier is charged at the last tier rate.
- A quantity of zero or less costs nothing.
tiered_total(qty: int, tiers: list<Tier>) → int
Where you start
def tiered_total(qty: int, tiers: list[Tier]) -> int:
Worked examples
| Call | Result |
|---|---|
tiered_total(60, [Tier(up_to=10, unit_price=100), Tier(up_to=50, unit_price=90), Tier(up_to=200, unit_price=80)]) | 5400 |
tiered_total(5, [Tier(up_to=10, unit_price=100), Tier(up_to=50, unit_price=90)]) | 500 |
tiered_total(300, [Tier(up_to=10, unit_price=100), Tier(up_to=50, unit_price=90)]) | 27100 |
tiered_total(0, [Tier(up_to=10, unit_price=100)]) | 0 |
Hint
Track how many units you have already priced. Each tier handles at most upTo minus that.
Reference solution in Python
def tiered_total(qty: int, tiers: list[Tier]) -> int:
if qty <= 0 or not tiers:
return 0
done = 0
total = 0
for t in tiers:
take = min(qty - done, t.up_to - done)
if take > 0:
total += take * t.unit_price
done += take
if done < qty:
total += (qty - done) * tiers[-1].unit_price
return total