Pick the coupon worth most
A customer has several coupons in their wallet and the checkout applies whichever saves them the most on this basket.
- A coupon takes its percentage off, but never more than its cap.
- Choose the coupon with the largest saving.
- If two save the same, take the one whose code sorts first.
- If nothing saves anything, return null.
best_coupon(basket_total: int, coupons: list<Coupon>) → string?
Where you start
def best_coupon(basket_total: int, coupons: list[Coupon]) -> str | None:
Worked examples
| Call | Result |
|---|---|
best_coupon(10000, [Coupon(code="TEN", percent_off=10, max_off=5000), Coupon(code="BIG", percent_off=50, max_off=2000)]) | "BIG" |
best_coupon(10000, [Coupon(code="ZED", percent_off=20, max_off=9000), Coupon(code="ACE", percent_off=20, max_off=9000)]) | "ACE" |
best_coupon(100, [Coupon(code="TINY", percent_off=0, max_off=500)]) | None |
best_coupon(10000, []) | None |
Hint
Work out each saving first, then compare. Integer division truncates, which is in the shop’s favour.
Reference solution in Python
def best_coupon(basket_total: int, coupons: list[Coupon]) -> str | None:
best_code = None
best_save = 0
for c in coupons:
save = min(basket_total * c.percent_off // 100, c.max_off)
if save <= 0:
continue
if save > best_save or (save == best_save and best_code is not None and c.code < best_code):
best_save, best_code = save, c.code
return best_code