Implement tiered shipping calculator
Company: Stripe
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Technical Screen
Quick Answer: Implement tiered shipping calculator evaluates algorithm design, data structures, correctness, complexity, edge cases, and implementation details in a realistic interview setting. A strong answer states assumptions, handles edge cases, explains trade-offs, and shows how to validate the result clearly.
Constraints
- destination is a string; quantity is an integer (may be 0 or negative).
- Exactly one of unitPrice / tiers / baseFlat+tiers is present per destination.
- Tiers are sorted ascending by upTo; the final tier's upTo is unbounded (Infinity or a large sentinel).
- Each upTo is inclusive; tiers are graduated (marginal), not flat-rate-of-the-whole-order.
- Unknown destination returns null/None; quantity <= 0 returns 0.
Examples
Input: ('US', 3, {'US': {'unitPrice': 5.0}})
Expected Output: 15.0
Explanation: Flat model: unitPrice 5.0 x 3 units = 15.0.
Input: ('US', 0, {'US': {'unitPrice': 5.0}})
Expected Output: 0.0
Explanation: Edge: quantity 0 always costs 0.0 regardless of model.
Input: ('US', 7, {'US': {'tiers': [{'upTo': 5, 'unitPrice': 10.0}, {'upTo': 10, 'unitPrice': 8.0}, {'upTo': 1000000, 'unitPrice': 6.0}]}})
Expected Output: 66.0
Explanation: Tiered: items 1-5 @10 (50) + items 6-7 @8 (16) = 66.0.
Input: ('US', 5, {'US': {'tiers': [{'upTo': 5, 'unitPrice': 10.0}, {'upTo': 10, 'unitPrice': 8.0}, {'upTo': 1000000, 'unitPrice': 6.0}]}})
Expected Output: 50.0
Explanation: Boundary: exactly at first cutoff (upTo 5, inclusive) -> 5 x 10 = 50.0.
Input: ('US', 10, {'US': {'tiers': [{'upTo': 5, 'unitPrice': 10.0}, {'upTo': 10, 'unitPrice': 8.0}, {'upTo': 1000000, 'unitPrice': 6.0}]}})
Expected Output: 90.0
Explanation: Boundary: at second cutoff -> items 1-5 @10 (50) + items 6-10 @8 (40) = 90.0.
Input: ('US', 12, {'US': {'tiers': [{'upTo': 5, 'unitPrice': 10.0}, {'upTo': 10, 'unitPrice': 8.0}, {'upTo': 1000000, 'unitPrice': 6.0}]}})
Expected Output: 102.0
Explanation: Spans all tiers: 5x10 + 5x8 + 2x6 = 50 + 40 + 12 = 102.0.
Input: ('US', 3, {'US': {'baseFlat': {'upTo': 3, 'amount': 20.0}, 'tiers': [{'upTo': 5, 'unitPrice': 10.0}, {'upTo': 10, 'unitPrice': 8.0}, {'upTo': 1000000, 'unitPrice': 6.0}]}})
Expected Output: 20.0
Explanation: baseFlat: quantity 3 == n, so just the flat fee F = 20.0 (no per-item tiering yet).
Input: ('US', 4, {'US': {'baseFlat': {'upTo': 3, 'amount': 20.0}, 'tiers': [{'upTo': 5, 'unitPrice': 10.0}, {'upTo': 10, 'unitPrice': 8.0}, {'upTo': 1000000, 'unitPrice': 6.0}]}})
Expected Output: 30.0
Explanation: Off-by-one boundary: F=20 for the first 3 items, then item 4 falls in tier1 @10 -> 20 + 10 = 30.0.
Input: ('US', 6, {'US': {'baseFlat': {'upTo': 3, 'amount': 20.0}, 'tiers': [{'upTo': 5, 'unitPrice': 10.0}, {'upTo': 10, 'unitPrice': 8.0}, {'upTo': 1000000, 'unitPrice': 6.0}]}})
Expected Output: 48.0
Explanation: F=20 + items 4-5 @10 (20) + item 6 @8 (8) = 48.0.
Input: ('US', 12, {'US': {'baseFlat': {'upTo': 3, 'amount': 20.0}, 'tiers': [{'upTo': 5, 'unitPrice': 10.0}, {'upTo': 10, 'unitPrice': 8.0}, {'upTo': 1000000, 'unitPrice': 6.0}]}})
Expected Output: 92.0
Explanation: F=20 + items 4-5 @10 (20) + items 6-10 @8 (40) + items 11-12 @6 (12) = 92.0.
Input: ('MARS', 5, {'US': {'unitPrice': 5.0}})
Expected Output: None
Explanation: Unknown destination is not present in config -> return None (null).
Input: ('US', -2, {'US': {'unitPrice': 5.0}})
Expected Output: 0.0
Explanation: Edge: negative quantity is non-positive -> 0.0.
Hints
- Dispatch on the shape of config[destination]: presence of unitPrice vs baseFlat vs tiers.
- For graduated tiers, track the previous tier's upTo; the current tier covers items (prev+1 .. min(upTo, quantity)).
- For the baseFlat model, charge F once, then start tier accounting at item n+1 — the classic off-by-one is charging item n twice or skipping item n+1.
- Handle quantity 0 / negative and unknown destination before touching tiers.