FA-60806 / Loyalty points ledgers / Open access
Purchased points with volume bonus: limit breach handling · case 01
A request that would exceed the annual limit is silently trimmed to the remaining allowance.
ROOT CAUSE
The limit check caps the request instead of rejecting it.
VERIFIED REPAIR
Reject the whole request when it would exceed the limit.
Unsuccessful approach: Trimming to the remaining allowance floored to thousands is still a partial fill.
Case contract
Input {requests:[pts], price_per_1000, tiers:[[min_base, bonus_bp]] ascending, annual_limit, bought_ytd}. Each request is floored to whole thousands ("too small" when that is 0). A request whose base would push purchased base points above annual_limit is rejected whole ("limit"); bonus points never count toward the limit. Bonus = floor(base*bp/10000) with bp from the highest tier whose min_base <= this request base. Price = base/1000*price_per_1000. Return {results:[[base,bonus,price]|reason], bought_ytd}.
Why this case matters
Member point balances, statements and the program liability depend on this ledger rule.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
bought = x['bought_ytd']
out = []
for req in x['requests']:
base = req // 1000 * 1000
if base == 0:
out.append('too small')
continue
base = min(base, x['annual_limit'] - bought)
if base <= 0:
out.append('limit')
continue
bp = 0
for mn, b in x['tiers']:
if base >= mn:
bp = b
bonus = base * bp // 10000
price = base // 1000 * x['price_per_1000']
bought += base
out.append([base, bonus, price])
return {'results': out, 'bought_ytd': bought}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['small buy', {'requests': [3501], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 20000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 25000}], ['big buy', {'requests': [21000], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1001], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 11000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20001], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4001}, {'results': ['limit'], 'bought_ytd': 4001}]], [['small buy', {'requests': [3502], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 40000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 45000}], ['big buy', {'requests': [21001], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1002], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 12000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20002], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4002}, {'results': ['limit'], 'bought_ytd': 4002}]], [['small buy', {'requests': [3503], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 60000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 65000}], ['big buy', {'requests': [21002], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1003], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 13000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20003], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4003}, {'results': ['limit'], 'bought_ytd': 4003}]], [['small buy', {'requests': [3504], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 80000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 85000}], ['big buy', {'requests': [21003], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1004], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 14000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20004], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4004}, {'results': ['limit'], 'bought_ytd': 4004}]], [['small buy', {'requests': [3505], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 100000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 105000}], ['big buy', {'requests': [21004], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1005], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 15000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20005], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4005}, {'results': ['limit'], 'bought_ytd': 4005}]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| small buy | {'bought_ytd': 3000, 'results': [[3000, 0, 3750]]} | {'bought_ytd': 3000, 'results': [[3000, 0, 3750]]} | Passed |
| tier edge | {'bought_ytd': 25000, 'results': [[5000, 500, 6250]]} | {'bought_ytd': 25000, 'results': [[5000, 500, 6250]]} | Passed |
| big buy | {'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]} | {'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]} | Passed |
| too small | {'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]} | {'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]} | Passed |
| limit hit | {'bought_ytd': 70000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], [5000, 500, 5000]]} | {'bought_ytd': 65000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit']} | Failed |
| bonus not limited | {'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]} | {'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]} | Passed |
| near limit | {'bought_ytd': 10000, 'results': [[5999, 599, 5000]]} | {'bought_ytd': 4001, 'results': ['limit']} | Failed |
SHA-256 / bb9dfe83e60d49d5189cf64948b4c3415f62c921bc2439a3e789aea6351046aa
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
bought = x['bought_ytd']
out = []
for req in x['requests']:
base = req // 1000 * 1000
if base == 0:
out.append('too small')
continue
base = min(base, (x['annual_limit'] - bought) // 1000 * 1000)
if base <= 0:
out.append('limit')
continue
bp = 0
for mn, b in x['tiers']:
if base >= mn:
bp = b
bonus = base * bp // 10000
price = base // 1000 * x['price_per_1000']
bought += base
out.append([base, bonus, price])
return {'results': out, 'bought_ytd': bought}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['small buy', {'requests': [3501], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 20000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 25000}], ['big buy', {'requests': [21000], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1001], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 11000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20001], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4001}, {'results': ['limit'], 'bought_ytd': 4001}]], [['small buy', {'requests': [3502], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 40000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 45000}], ['big buy', {'requests': [21001], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1002], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 12000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20002], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4002}, {'results': ['limit'], 'bought_ytd': 4002}]], [['small buy', {'requests': [3503], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 60000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 65000}], ['big buy', {'requests': [21002], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1003], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 13000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20003], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4003}, {'results': ['limit'], 'bought_ytd': 4003}]], [['small buy', {'requests': [3504], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 80000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 85000}], ['big buy', {'requests': [21003], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1004], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 14000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20004], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4004}, {'results': ['limit'], 'bought_ytd': 4004}]], [['small buy', {'requests': [3505], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 100000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 105000}], ['big buy', {'requests': [21004], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1005], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 15000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20005], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4005}, {'results': ['limit'], 'bought_ytd': 4005}]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| small buy | {'bought_ytd': 3000, 'results': [[3000, 0, 3750]]} | {'bought_ytd': 3000, 'results': [[3000, 0, 3750]]} | Passed |
| tier edge | {'bought_ytd': 25000, 'results': [[5000, 500, 6250]]} | {'bought_ytd': 25000, 'results': [[5000, 500, 6250]]} | Passed |
| big buy | {'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]} | {'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]} | Passed |
| too small | {'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]} | {'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]} | Passed |
| limit hit | {'bought_ytd': 70000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], [5000, 500, 5000]]} | {'bought_ytd': 65000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit']} | Failed |
| bonus not limited | {'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]} | {'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]} | Passed |
| near limit | {'bought_ytd': 9001, 'results': [[5000, 500, 5000]]} | {'bought_ytd': 4001, 'results': ['limit']} | Failed |
SHA-256 / 9210c178514de7edb9ac09da22e3a7016a695daca224e5867d923ebb213132a4
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
bought = x['bought_ytd']
out = []
for req in x['requests']:
base = req // 1000 * 1000
if base == 0:
out.append('too small')
continue
if bought + base > x['annual_limit']:
out.append('limit')
continue
bp = 0
for mn, b in x['tiers']:
if base >= mn:
bp = b
bonus = base * bp // 10000
price = base // 1000 * x['price_per_1000']
bought += base
out.append([base, bonus, price])
return {'results': out, 'bought_ytd': bought}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['small buy', {'requests': [3501], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 20000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 25000}], ['big buy', {'requests': [21000], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1001], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 11000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20001], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4001}, {'results': ['limit'], 'bought_ytd': 4001}]], [['small buy', {'requests': [3502], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 40000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 45000}], ['big buy', {'requests': [21001], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1002], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 12000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20002], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4002}, {'results': ['limit'], 'bought_ytd': 4002}]], [['small buy', {'requests': [3503], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 60000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 65000}], ['big buy', {'requests': [21002], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1003], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 13000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20003], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4003}, {'results': ['limit'], 'bought_ytd': 4003}]], [['small buy', {'requests': [3504], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 80000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 85000}], ['big buy', {'requests': [21003], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1004], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 14000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20004], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4004}, {'results': ['limit'], 'bought_ytd': 4004}]], [['small buy', {'requests': [3505], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[3000, 0, 3750]], 'bought_ytd': 3000}], ['tier edge', {'requests': [5000], 'price_per_1000': 1250, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 1000000, 'bought_ytd': 100000}, {'results': [[5000, 500, 6250]], 'bought_ytd': 105000}], ['big buy', {'requests': [21004], 'price_per_1000': 1100, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': [[21000, 5250, 23100]], 'bought_ytd': 21000}], ['too small', {'requests': [999, 1005], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 100000, 'bought_ytd': 0}, {'results': ['too small', [1000, 0, 1000]], 'bought_ytd': 1000}], ['limit hit', {'requests': [30000, 30000, 15000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 70000, 'bought_ytd': 5000}, {'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit'], 'bought_ytd': 65000}], ['bonus not limited', {'requests': [20000, 20005], 'price_per_1000': 900, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 40000, 'bought_ytd': 0}, {'results': [[20000, 5000, 18000], [20000, 5000, 18000]], 'bought_ytd': 40000}], ['near limit', {'requests': [7000], 'price_per_1000': 1000, 'tiers': [[0, 0], [5000, 1000], [20000, 2500]], 'annual_limit': 10000, 'bought_ytd': 4005}, {'results': ['limit'], 'bought_ytd': 4005}]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| small buy | {'bought_ytd': 3000, 'results': [[3000, 0, 3750]]} | {'bought_ytd': 3000, 'results': [[3000, 0, 3750]]} | Passed |
| tier edge | {'bought_ytd': 25000, 'results': [[5000, 500, 6250]]} | {'bought_ytd': 25000, 'results': [[5000, 500, 6250]]} | Passed |
| big buy | {'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]} | {'bought_ytd': 21000, 'results': [[21000, 5250, 23100]]} | Passed |
| too small | {'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]} | {'bought_ytd': 1000, 'results': ['too small', [1000, 0, 1000]]} | Passed |
| limit hit | {'bought_ytd': 65000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit']} | {'bought_ytd': 65000, 'results': [[30000, 7500, 30000], [30000, 7500, 30000], 'limit']} | Passed |
| bonus not limited | {'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]} | {'bought_ytd': 40000, 'results': [[20000, 5000, 18000], [20000, 5000, 18000]]} | Passed |
| near limit | {'bought_ytd': 4001, 'results': ['limit']} | {'bought_ytd': 4001, 'results': ['limit']} | Passed |
SHA-256 / 81a17f22fd26ace258d124ec03de8e821856178616e6689b9802a183e81c27c5
Verification & scope
Stipulated bounded loyalty-program model with explicit toy rules; not any real program terms. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:46:49.068790+00:00.
Case digest / ec9514a3c84c9f81e0d7875095aeda36d9575e19b36e9f7c64fc373b36c700fd