FA-68376 / Toll and parking fee computation / Open access
Tiered parking rate table: tiers are scanned in reverse order · case 01
Tiered parking rate table returns a wrong result when tiers are scanned in reverse order.
ROOT CAUSE
An unsorted rate table matches the first listed tier that fits rather than the smallest.
VERIFIED REPAIR
Restore the tier ordering rule so that the step reads `tiers = sorted(x['tiers'])`.
Unsuccessful approach: Descending order always matches the largest tier.
Case contract
Input {minutes, tiers: [[upto minutes, cumulative price]] in any order, extra_per: [block minutes, cents], max}. A stay of 0 minutes is free. Tiers are applied in ascending upto order and a stay of exactly upto minutes belongs to that tier (price capped at max). Beyond the last tier each started block after its upto adds the block price; the whole fee is capped at max.
Why this case matters
Fee engines bill customers in integer cents; a wrong boundary, rounding stage or cap scope silently over- or under-charges.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
m = x['minutes']
tiers = x['tiers']
if m <= 0:
return 0
for upto, price in tiers:
if m <= upto:
return min(price, x['max'])
last_upto, last_price = tiers[-1]
blk, add = x['extra_per']
extra = -(-(m - last_upto) // blk)
return min(last_price + extra * add, x['max'])
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 330, 'tiers': [[210, 250], [330, 900]], 'extra_per': [15, 150], 'max': 4000}, 900), ({'minutes': 361, 'tiers': [[360, 950], [240, 450], [180, 200]], 'extra_per': [60, 100], 'max': 4000}, 1050), ({'minutes': 240, 'tiers': [[300, 850], [240, 550], [330, 900], [360, 1600]], 'extra_per': [15, 50], 'max': 4000}, 550), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 602, 'tiers': [[120, 850], [360, 1900], [270, 1700], [240, 1200]], 'extra_per': [20, 150], 'max': 4000}, 3850), ({'minutes': 121, 'tiers': [[120, 900]], 'extra_per': [30, 50], 'max': 2500}, 950)], [({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 330, 'tiers': [[330, 1600]], 'extra_per': [20, 50], 'max': 4000}, 1600), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 157, 'tiers': [[60, 1250], [150, 1700]], 'extra_per': [30, 150], 'max': 1500}, 1500), ({'minutes': 30, 'tiers': [[180, 450], [30, 200], [300, 1600]], 'extra_per': [20, 100], 'max': 4000}, 200), ({'minutes': 352, 'tiers': [[330, 150]], 'extra_per': [60, 150], 'max': 2500}, 300), ({'minutes': 375, 'tiers': [[360, 1950], [60, 750], [180, 1150], [30, 700]], 'extra_per': [60, 50], 'max': 4000}, 2000), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 91, 'tiers': [[90, 550], [330, 1800], [300, 1450]], 'extra_per': [60, 100], 'max': 4000}, 1450), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 91, 'tiers': [[240, 2000], [90, 1100], [120, 1150]], 'extra_per': [20, 50], 'max': 4000}, 1150), ({'minutes': 517, 'tiers': [[240, 2000]], 'extra_per': [15, 100], 'max': 1500}, 1500), ({'minutes': 60, 'tiers': [[120, 1600], [90, 1050], [60, 250], [300, 1900]], 'extra_per': [15, 100], 'max': 4000}, 250), ({'minutes': 288, 'tiers': [[90, 200], [210, 800]], 'extra_per': [15, 150], 'max': 1500}, 1500)], [({'minutes': 544, 'tiers': [[270, 200], [360, 1600]], 'extra_per': [60, 100], 'max': 1500}, 1500), ({'minutes': 885, 'tiers': [[210, 600], [180, 100]], 'extra_per': [20, 50], 'max': 4000}, 2300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 30, 'tiers': [[300, 1950], [30, 300], [210, 550]], 'extra_per': [30, 50], 'max': 1500}, 300), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 211, 'tiers': [[360, 1600], [300, 1250], [60, 800], [210, 1000]], 'extra_per': [20, 50], 'max': 2500}, 1250), ({'minutes': 267, 'tiers': [[90, 1250], [180, 1350], [210, 1500], [270, 1900]], 'extra_per': [60, 150], 'max': 4000}, 1900), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 47, 'tiers': [[300, 1650], [60, 1350]], 'extra_per': [30, 100], 'max': 4000}, 1350), ({'minutes': 301, 'tiers': [[300, 1550]], 'extra_per': [30, 150], 'max': 2500}, 1700), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 210, 'tiers': [[210, 100]], 'extra_per': [20, 150], 'max': 2500}, 100), ({'minutes': 125, 'tiers': [[300, 1300], [180, 300], [240, 1050], [210, 650]], 'extra_per': [20, 100], 'max': 1500}, 300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 900, 'tiers': [[120, 200], [150, 950], [300, 1450]], 'extra_per': [15, 50], 'max': 4000}, 3450)]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check('fee oracle' + ' %d' % i, 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 |
|---|---|---|---|
| fee oracle 0 | 2500 | 2500 | Passed |
| fee oracle 1 | 900 | 900 | Passed |
| fee oracle 2 | 600 | 1050 | Failed |
| fee oracle 3 | 850 | 550 | Failed |
| fee oracle 4 | 300 | 300 | Passed |
| fee oracle 5 | 150 | 150 | Passed |
| fee oracle 6 | 4000 | 3850 | Failed |
| fee oracle 7 | 950 | 950 | Passed |
SHA-256 / 7df0417a48b7c41834771d0dfc5883857ee37f9b6013578a95705be81b131839
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
m = x['minutes']
tiers = sorted(x['tiers'], reverse=True)
if m <= 0:
return 0
for upto, price in tiers:
if m <= upto:
return min(price, x['max'])
last_upto, last_price = tiers[-1]
blk, add = x['extra_per']
extra = -(-(m - last_upto) // blk)
return min(last_price + extra * add, x['max'])
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 330, 'tiers': [[210, 250], [330, 900]], 'extra_per': [15, 150], 'max': 4000}, 900), ({'minutes': 361, 'tiers': [[360, 950], [240, 450], [180, 200]], 'extra_per': [60, 100], 'max': 4000}, 1050), ({'minutes': 240, 'tiers': [[300, 850], [240, 550], [330, 900], [360, 1600]], 'extra_per': [15, 50], 'max': 4000}, 550), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 602, 'tiers': [[120, 850], [360, 1900], [270, 1700], [240, 1200]], 'extra_per': [20, 150], 'max': 4000}, 3850), ({'minutes': 121, 'tiers': [[120, 900]], 'extra_per': [30, 50], 'max': 2500}, 950)], [({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 330, 'tiers': [[330, 1600]], 'extra_per': [20, 50], 'max': 4000}, 1600), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 157, 'tiers': [[60, 1250], [150, 1700]], 'extra_per': [30, 150], 'max': 1500}, 1500), ({'minutes': 30, 'tiers': [[180, 450], [30, 200], [300, 1600]], 'extra_per': [20, 100], 'max': 4000}, 200), ({'minutes': 352, 'tiers': [[330, 150]], 'extra_per': [60, 150], 'max': 2500}, 300), ({'minutes': 375, 'tiers': [[360, 1950], [60, 750], [180, 1150], [30, 700]], 'extra_per': [60, 50], 'max': 4000}, 2000), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 91, 'tiers': [[90, 550], [330, 1800], [300, 1450]], 'extra_per': [60, 100], 'max': 4000}, 1450), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 91, 'tiers': [[240, 2000], [90, 1100], [120, 1150]], 'extra_per': [20, 50], 'max': 4000}, 1150), ({'minutes': 517, 'tiers': [[240, 2000]], 'extra_per': [15, 100], 'max': 1500}, 1500), ({'minutes': 60, 'tiers': [[120, 1600], [90, 1050], [60, 250], [300, 1900]], 'extra_per': [15, 100], 'max': 4000}, 250), ({'minutes': 288, 'tiers': [[90, 200], [210, 800]], 'extra_per': [15, 150], 'max': 1500}, 1500)], [({'minutes': 544, 'tiers': [[270, 200], [360, 1600]], 'extra_per': [60, 100], 'max': 1500}, 1500), ({'minutes': 885, 'tiers': [[210, 600], [180, 100]], 'extra_per': [20, 50], 'max': 4000}, 2300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 30, 'tiers': [[300, 1950], [30, 300], [210, 550]], 'extra_per': [30, 50], 'max': 1500}, 300), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 211, 'tiers': [[360, 1600], [300, 1250], [60, 800], [210, 1000]], 'extra_per': [20, 50], 'max': 2500}, 1250), ({'minutes': 267, 'tiers': [[90, 1250], [180, 1350], [210, 1500], [270, 1900]], 'extra_per': [60, 150], 'max': 4000}, 1900), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 47, 'tiers': [[300, 1650], [60, 1350]], 'extra_per': [30, 100], 'max': 4000}, 1350), ({'minutes': 301, 'tiers': [[300, 1550]], 'extra_per': [30, 150], 'max': 2500}, 1700), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 210, 'tiers': [[210, 100]], 'extra_per': [20, 150], 'max': 2500}, 100), ({'minutes': 125, 'tiers': [[300, 1300], [180, 300], [240, 1050], [210, 650]], 'extra_per': [20, 100], 'max': 1500}, 300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 900, 'tiers': [[120, 200], [150, 950], [300, 1450]], 'extra_per': [15, 50], 'max': 4000}, 3450)]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check('fee oracle' + ' %d' % i, 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 |
|---|---|---|---|
| fee oracle 0 | 2500 | 2500 | Passed |
| fee oracle 1 | 900 | 900 | Passed |
| fee oracle 2 | 600 | 1050 | Failed |
| fee oracle 3 | 1600 | 550 | Failed |
| fee oracle 4 | 800 | 300 | Failed |
| fee oracle 5 | 300 | 150 | Failed |
| fee oracle 6 | 4000 | 3850 | Failed |
| fee oracle 7 | 950 | 950 | Passed |
SHA-256 / 28a464d8290e8f6223854f119bd6bd7a98d1590aae10829633d71c00a4368cb1
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
m = x['minutes']
tiers = sorted(x['tiers'])
if m <= 0:
return 0
for upto, price in tiers:
if m <= upto:
return min(price, x['max'])
last_upto, last_price = tiers[-1]
blk, add = x['extra_per']
extra = -(-(m - last_upto) // blk)
return min(last_price + extra * add, x['max'])
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 330, 'tiers': [[210, 250], [330, 900]], 'extra_per': [15, 150], 'max': 4000}, 900), ({'minutes': 361, 'tiers': [[360, 950], [240, 450], [180, 200]], 'extra_per': [60, 100], 'max': 4000}, 1050), ({'minutes': 240, 'tiers': [[300, 850], [240, 550], [330, 900], [360, 1600]], 'extra_per': [15, 50], 'max': 4000}, 550), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 602, 'tiers': [[120, 850], [360, 1900], [270, 1700], [240, 1200]], 'extra_per': [20, 150], 'max': 4000}, 3850), ({'minutes': 121, 'tiers': [[120, 900]], 'extra_per': [30, 50], 'max': 2500}, 950)], [({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 330, 'tiers': [[330, 1600]], 'extra_per': [20, 50], 'max': 4000}, 1600), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 157, 'tiers': [[60, 1250], [150, 1700]], 'extra_per': [30, 150], 'max': 1500}, 1500), ({'minutes': 30, 'tiers': [[180, 450], [30, 200], [300, 1600]], 'extra_per': [20, 100], 'max': 4000}, 200), ({'minutes': 352, 'tiers': [[330, 150]], 'extra_per': [60, 150], 'max': 2500}, 300), ({'minutes': 375, 'tiers': [[360, 1950], [60, 750], [180, 1150], [30, 700]], 'extra_per': [60, 50], 'max': 4000}, 2000), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 91, 'tiers': [[90, 550], [330, 1800], [300, 1450]], 'extra_per': [60, 100], 'max': 4000}, 1450), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 91, 'tiers': [[240, 2000], [90, 1100], [120, 1150]], 'extra_per': [20, 50], 'max': 4000}, 1150), ({'minutes': 517, 'tiers': [[240, 2000]], 'extra_per': [15, 100], 'max': 1500}, 1500), ({'minutes': 60, 'tiers': [[120, 1600], [90, 1050], [60, 250], [300, 1900]], 'extra_per': [15, 100], 'max': 4000}, 250), ({'minutes': 288, 'tiers': [[90, 200], [210, 800]], 'extra_per': [15, 150], 'max': 1500}, 1500)], [({'minutes': 544, 'tiers': [[270, 200], [360, 1600]], 'extra_per': [60, 100], 'max': 1500}, 1500), ({'minutes': 885, 'tiers': [[210, 600], [180, 100]], 'extra_per': [20, 50], 'max': 4000}, 2300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 30, 'tiers': [[300, 1950], [30, 300], [210, 550]], 'extra_per': [30, 50], 'max': 1500}, 300), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 211, 'tiers': [[360, 1600], [300, 1250], [60, 800], [210, 1000]], 'extra_per': [20, 50], 'max': 2500}, 1250), ({'minutes': 267, 'tiers': [[90, 1250], [180, 1350], [210, 1500], [270, 1900]], 'extra_per': [60, 150], 'max': 4000}, 1900), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 47, 'tiers': [[300, 1650], [60, 1350]], 'extra_per': [30, 100], 'max': 4000}, 1350), ({'minutes': 301, 'tiers': [[300, 1550]], 'extra_per': [30, 150], 'max': 2500}, 1700), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 210, 'tiers': [[210, 100]], 'extra_per': [20, 150], 'max': 2500}, 100), ({'minutes': 125, 'tiers': [[300, 1300], [180, 300], [240, 1050], [210, 650]], 'extra_per': [20, 100], 'max': 1500}, 300), ({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 900, 'tiers': [[120, 200], [150, 950], [300, 1450]], 'extra_per': [15, 50], 'max': 4000}, 3450)]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check('fee oracle' + ' %d' % i, 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 |
|---|---|---|---|
| fee oracle 0 | 2500 | 2500 | Passed |
| fee oracle 1 | 900 | 900 | Passed |
| fee oracle 2 | 1050 | 1050 | Passed |
| fee oracle 3 | 550 | 550 | Passed |
| fee oracle 4 | 300 | 300 | Passed |
| fee oracle 5 | 150 | 150 | Passed |
| fee oracle 6 | 3850 | 3850 | Passed |
| fee oracle 7 | 950 | 950 | Passed |
SHA-256 / 71f023823c1493466298990671c396dc3074d2caa4f1e2155f95cbed39e608f6
Verification & scope
A deterministic, bounded toy model with a stipulated contract; it makes no claim of conformance to any agency manual or standard. 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:48:01.599023+00:00.
Case digest / f200e01559fcfa96d78618524145796eb4a865260bd1607026f0e362c5a69a98