FA-68386 / Toll and parking fee computation / Open access
Tiered parking rate table: a zero-minute stay pays the first tier · case 01
Tiered parking rate table returns a wrong result when a zero-minute stay pays the first tier.
ROOT CAUSE
Entry and exit in the same minute is charged the first tier.
VERIFIED REPAIR
Restore the zero-length stay rule so that the step reads `if m <= 0:`.
Unsuccessful approach: Making one-minute stays free extends the free window beyond the contract.
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 = 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': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 301, 'tiers': [[180, 800], [300, 1350]], 'extra_per': [20, 100], 'max': 2500}, 1450), ({'minutes': 183, 'tiers': [[30, 450], [300, 900], [330, 1550]], 'extra_per': [30, 50], 'max': 4000}, 900), ({'minutes': 241, 'tiers': [[240, 1350]], 'extra_per': [30, 50], 'max': 1500}, 1400), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 150, 'tiers': [[150, 200], [360, 450]], 'extra_per': [15, 150], 'max': 1500}, 200), ({'minutes': 345, 'tiers': [[300, 1350], [150, 1150], [360, 1800], [180, 1200]], 'extra_per': [15, 150], 'max': 2500}, 1800)], [({'minutes': 185, 'tiers': [[90, 1200], [150, 1800]], 'extra_per': [20, 50], 'max': 2500}, 1900), ({'minutes': 67, 'tiers': [[60, 500], [90, 1400], [210, 1800]], 'extra_per': [15, 150], 'max': 2500}, 1400), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 360, 'tiers': [[90, 450], [330, 1500], [360, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 233, 'tiers': [[270, 550], [120, 350], [330, 1600], [180, 500]], 'extra_per': [60, 50], 'max': 2500}, 550)], [({'minutes': 60, 'tiers': [[60, 750]], 'extra_per': [30, 150], 'max': 1500}, 750), ({'minutes': 350, 'tiers': [[150, 250]], 'extra_per': [15, 150], 'max': 2500}, 2350), ({'minutes': 425, 'tiers': [[120, 500], [180, 1250], [240, 1950], [90, 150]], 'extra_per': [30, 50], 'max': 4000}, 2300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 184, 'tiers': [[360, 1200], [90, 300], [300, 1100], [120, 1050]], 'extra_per': [30, 50], 'max': 1500}, 1100), ({'minutes': 302, 'tiers': [[30, 150], [90, 500], [270, 650], [360, 1500]], 'extra_per': [30, 50], 'max': 4000}, 1500), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 181, 'tiers': [[120, 550], [180, 1800], [210, 1850]], 'extra_per': [60, 150], 'max': 4000}, 1850), ({'minutes': 82, 'tiers': [[150, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'minutes': 241, 'tiers': [[60, 350], [240, 1350]], 'extra_per': [20, 50], 'max': 2500}, 1400), ({'minutes': 0, 'tiers': [[300, 1750], [150, 650], [210, 1250]], 'extra_per': [30, 150], 'max': 2500}, 0), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'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': 594, 'tiers': [[90, 250], [120, 1400]], 'extra_per': [15, 100], 'max': 1500}, 1500), ({'minutes': 1, 'tiers': [[270, 1150]], 'extra_per': [20, 150], 'max': 4000}, 1150), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'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': 151, 'tiers': [[30, 200], [240, 1250]], 'extra_per': [15, 100], 'max': 1500}, 1250), ({'minutes': 291, 'tiers': [[300, 1700], [30, 500], [150, 1400]], 'extra_per': [30, 150], 'max': 4000}, 1700), ({'minutes': 68, 'tiers': [[120, 1100], [330, 1550]], 'extra_per': [30, 150], 'max': 4000}, 1100)]]
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 | 150 | 150 | Passed |
| fee oracle 2 | 1450 | 1450 | Passed |
| fee oracle 3 | 900 | 900 | Passed |
| fee oracle 4 | 1400 | 1400 | Passed |
| fee oracle 5 | 300 | 0 | Failed |
| fee oracle 6 | 200 | 200 | Passed |
| fee oracle 7 | 1800 | 1800 | Passed |
SHA-256 / d1f4b467c18f9fc45bdbb83ee569bd8956728ae913f6af7a90fc33ab34c7f7b6
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'])
if m <= 1:
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': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 301, 'tiers': [[180, 800], [300, 1350]], 'extra_per': [20, 100], 'max': 2500}, 1450), ({'minutes': 183, 'tiers': [[30, 450], [300, 900], [330, 1550]], 'extra_per': [30, 50], 'max': 4000}, 900), ({'minutes': 241, 'tiers': [[240, 1350]], 'extra_per': [30, 50], 'max': 1500}, 1400), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 150, 'tiers': [[150, 200], [360, 450]], 'extra_per': [15, 150], 'max': 1500}, 200), ({'minutes': 345, 'tiers': [[300, 1350], [150, 1150], [360, 1800], [180, 1200]], 'extra_per': [15, 150], 'max': 2500}, 1800)], [({'minutes': 185, 'tiers': [[90, 1200], [150, 1800]], 'extra_per': [20, 50], 'max': 2500}, 1900), ({'minutes': 67, 'tiers': [[60, 500], [90, 1400], [210, 1800]], 'extra_per': [15, 150], 'max': 2500}, 1400), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 360, 'tiers': [[90, 450], [330, 1500], [360, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 233, 'tiers': [[270, 550], [120, 350], [330, 1600], [180, 500]], 'extra_per': [60, 50], 'max': 2500}, 550)], [({'minutes': 60, 'tiers': [[60, 750]], 'extra_per': [30, 150], 'max': 1500}, 750), ({'minutes': 350, 'tiers': [[150, 250]], 'extra_per': [15, 150], 'max': 2500}, 2350), ({'minutes': 425, 'tiers': [[120, 500], [180, 1250], [240, 1950], [90, 150]], 'extra_per': [30, 50], 'max': 4000}, 2300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 184, 'tiers': [[360, 1200], [90, 300], [300, 1100], [120, 1050]], 'extra_per': [30, 50], 'max': 1500}, 1100), ({'minutes': 302, 'tiers': [[30, 150], [90, 500], [270, 650], [360, 1500]], 'extra_per': [30, 50], 'max': 4000}, 1500), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 181, 'tiers': [[120, 550], [180, 1800], [210, 1850]], 'extra_per': [60, 150], 'max': 4000}, 1850), ({'minutes': 82, 'tiers': [[150, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'minutes': 241, 'tiers': [[60, 350], [240, 1350]], 'extra_per': [20, 50], 'max': 2500}, 1400), ({'minutes': 0, 'tiers': [[300, 1750], [150, 650], [210, 1250]], 'extra_per': [30, 150], 'max': 2500}, 0), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'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': 594, 'tiers': [[90, 250], [120, 1400]], 'extra_per': [15, 100], 'max': 1500}, 1500), ({'minutes': 1, 'tiers': [[270, 1150]], 'extra_per': [20, 150], 'max': 4000}, 1150), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'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': 151, 'tiers': [[30, 200], [240, 1250]], 'extra_per': [15, 100], 'max': 1500}, 1250), ({'minutes': 291, 'tiers': [[300, 1700], [30, 500], [150, 1400]], 'extra_per': [30, 150], 'max': 4000}, 1700), ({'minutes': 68, 'tiers': [[120, 1100], [330, 1550]], 'extra_per': [30, 150], 'max': 4000}, 1100)]]
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 | 0 | 150 | Failed |
| fee oracle 2 | 1450 | 1450 | Passed |
| fee oracle 3 | 900 | 900 | Passed |
| fee oracle 4 | 1400 | 1400 | Passed |
| fee oracle 5 | 0 | 0 | Passed |
| fee oracle 6 | 200 | 200 | Passed |
| fee oracle 7 | 1800 | 1800 | Passed |
SHA-256 / 6a7262ee25f63b44df9ff6b18bbf4b91174889a49d4531df6e40a417652a073a
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': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 301, 'tiers': [[180, 800], [300, 1350]], 'extra_per': [20, 100], 'max': 2500}, 1450), ({'minutes': 183, 'tiers': [[30, 450], [300, 900], [330, 1550]], 'extra_per': [30, 50], 'max': 4000}, 900), ({'minutes': 241, 'tiers': [[240, 1350]], 'extra_per': [30, 50], 'max': 1500}, 1400), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 150, 'tiers': [[150, 200], [360, 450]], 'extra_per': [15, 150], 'max': 1500}, 200), ({'minutes': 345, 'tiers': [[300, 1350], [150, 1150], [360, 1800], [180, 1200]], 'extra_per': [15, 150], 'max': 2500}, 1800)], [({'minutes': 185, 'tiers': [[90, 1200], [150, 1800]], 'extra_per': [20, 50], 'max': 2500}, 1900), ({'minutes': 67, 'tiers': [[60, 500], [90, 1400], [210, 1800]], 'extra_per': [15, 150], 'max': 2500}, 1400), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150), ({'minutes': 360, 'tiers': [[90, 450], [330, 1500], [360, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'minutes': 60, 'tiers': [[60, 300], [120, 500], [240, 800]], 'extra_per': [60, 200], 'max': 2000}, 300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 233, 'tiers': [[270, 550], [120, 350], [330, 1600], [180, 500]], 'extra_per': [60, 50], 'max': 2500}, 550)], [({'minutes': 60, 'tiers': [[60, 750]], 'extra_per': [30, 150], 'max': 1500}, 750), ({'minutes': 350, 'tiers': [[150, 250]], 'extra_per': [15, 150], 'max': 2500}, 2350), ({'minutes': 425, 'tiers': [[120, 500], [180, 1250], [240, 1950], [90, 150]], 'extra_per': [30, 50], 'max': 4000}, 2300), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'minutes': 0, 'tiers': [[60, 300]], 'extra_per': [30, 100], 'max': 1500}, 0), ({'minutes': 184, 'tiers': [[360, 1200], [90, 300], [300, 1100], [120, 1050]], 'extra_per': [30, 50], 'max': 1500}, 1100), ({'minutes': 302, 'tiers': [[30, 150], [90, 500], [270, 650], [360, 1500]], 'extra_per': [30, 50], 'max': 4000}, 1500), ({'minutes': 1, 'tiers': [[30, 150], [60, 300]], 'extra_per': [30, 100], 'max': 1500}, 150)], [({'minutes': 1000, 'tiers': [[90, 400], [180, 700]], 'extra_per': [45, 150], 'max': 2500}, 2500), ({'minutes': 181, 'tiers': [[120, 550], [180, 1800], [210, 1850]], 'extra_per': [60, 150], 'max': 4000}, 1850), ({'minutes': 82, 'tiers': [[150, 1900]], 'extra_per': [20, 150], 'max': 2500}, 1900), ({'minutes': 241, 'tiers': [[60, 350], [240, 1350]], 'extra_per': [20, 50], 'max': 2500}, 1400), ({'minutes': 0, 'tiers': [[300, 1750], [150, 650], [210, 1250]], 'extra_per': [30, 150], 'max': 2500}, 0), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'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': 594, 'tiers': [[90, 250], [120, 1400]], 'extra_per': [15, 100], 'max': 1500}, 1500), ({'minutes': 1, 'tiers': [[270, 1150]], 'extra_per': [20, 150], 'max': 4000}, 1150), ({'minutes': 250, 'tiers': [[240, 800], [60, 300], [120, 500]], 'extra_per': [60, 200], 'max': 2000}, 1000), ({'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': 151, 'tiers': [[30, 200], [240, 1250]], 'extra_per': [15, 100], 'max': 1500}, 1250), ({'minutes': 291, 'tiers': [[300, 1700], [30, 500], [150, 1400]], 'extra_per': [30, 150], 'max': 4000}, 1700), ({'minutes': 68, 'tiers': [[120, 1100], [330, 1550]], 'extra_per': [30, 150], 'max': 4000}, 1100)]]
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 | 150 | 150 | Passed |
| fee oracle 2 | 1450 | 1450 | Passed |
| fee oracle 3 | 900 | 900 | Passed |
| fee oracle 4 | 1400 | 1400 | Passed |
| fee oracle 5 | 0 | 0 | Passed |
| fee oracle 6 | 200 | 200 | Passed |
| fee oracle 7 | 1800 | 1800 | Passed |
SHA-256 / 1181acefc4e817ebb47d9a0e0ede0caf1eb383909c969a0b3aefbe7fd2d054f1
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.696836+00:00.
Case digest / 71a94692614aa29fcee4d9f732fd47b02c998543045bda269b594f72aca0dc33