FA-68731 / Toll and parking fee computation / Open access
Open-road gantry trip building: the trip gap is measured from the first read of the trip · case 01
Open-road gantry trip building returns a wrong result when the trip gap is measured from the first read of the trip.
ROOT CAUSE
Long multi-gantry trips are split because the gap is measured from trip start.
VERIFIED REPAIR
Restore the trip gap anchor rule so that the step reads `trips[-1]['t'] = t`.
Unsuccessful approach: Advancing the anchor only partially still splits long trips.
Case contract
Input {reads: [[minute, gantry, direction]] unordered, dedupe, max_gap, price per gantry, trip_cap}. Reads are sorted; a read of the same gantry within dedupe minutes (inclusive) of the last kept read of that gantry is dropped. Kept reads join the current trip when the direction matches and the gap from the trip's latest read is <= max_gap, else start a new trip. Each trip pays min(trip_cap, sum of its gantry prices). Return [trips, total].
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):
reads = sorted(x['reads'])
kept = []
lastg = {}
for t, g, d in reads:
if g in lastg and t - lastg[g] <= x['dedupe']:
continue
lastg[g] = t
kept.append((t, g, d))
trips = []
for t, g, d in kept:
if trips and trips[-1]['d'] == d and t - trips[-1]['t'] <= x['max_gap']:
trips[-1]['g'].append(g)
else:
trips.append({'d': d, 't': t, 'g': [g]})
total = sum(min(x['trip_cap'], sum(x['price'][g] for g in tr['g'])) for tr in trips)
return [len(trips), total]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'reads': [[38, 3, 'S'], [41, 3, 'S'], [48, 4, 'S'], [68, 2, 'S'], [78, 0, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [150, 110, 110, 110, 200, 75], 'trip_cap': 900}, [1, 570]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[8, 1, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 75, 75, 150, 75, 150], 'trip_cap': 400}, [1, 75]), ({'reads': [[45, 4, 'S'], [48, 4, 'S'], [48, 3, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 150, 200, 75, 200, 200], 'trip_cap': 900}, [1, 275]), ({'reads': [[39, 2, 'S'], [59, 0, 'S'], [104, 4, 'S'], [114, 3, 'S'], [145, 5, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 75, 110, 110, 150, 110], 'trip_cap': 900}, [3, 555]), ({'reads': [[35, 2, 'S'], [32, 2, 'S'], [12, 5, 'S'], [4, 3, 'S'], [7, 4, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 75, 110, 150, 150, 200], 'trip_cap': 600}, [1, 600]), ({'reads': [[32, 3, 'N'], [87, 5, 'N'], [107, 5, 'N'], [153, 3, 'S'], [2, 4, 'S'], [77, 1, 'N'], [152, 3, 'N'], [89, 5, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 110, 150, 200, 75, 110], 'trip_cap': 600}, [4, 805]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350])], [({'reads': [[132, 4, 'N'], [82, 0, 'N'], [133, 5, 'N'], [72, 2, 'N'], [102, 1, 'N'], [22, 5, 'N'], [27, 3, 'N'], [17, 3, 'N'], [72, 2, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 110, 75, 200, 110, 110], 'trip_cap': 600}, [3, 1025]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[8, 1, 'N'], [203, 3, 'S'], [128, 0, 'S'], [83, 0, 'S'], [175, 1, 'S'], [173, 1, 'S'], [53, 0, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 75, 200, 200, 150, 150], 'trip_cap': 600}, [6, 800]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[38, 0, 'N'], [40, 0, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 110, 200, 75, 150, 150], 'trip_cap': 600}, [1, 200]), ({'reads': [[62, 3, 'N'], [115, 3, 'N'], [64, 0, 'N'], [145, 4, 'N'], [42, 1, 'N'], [64, 3, 'N'], [37, 5, 'N'], [84, 4, 'N'], [114, 1, 'N'], [63, 5, 'N'], [116, 1, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 75, 150, 150, 110, 110], 'trip_cap': 900}, [1, 900]), ({'reads': [[37, 5, 'S'], [67, 2, 'S'], [72, 0, 'S'], [75, 0, 'S'], [103, 1, 'S'], [123, 4, 'S'], [153, 5, 'S'], [184, 4, 'S'], [204, 3, 'S'], [204, 3, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [75, 200, 200, 75, 110, 150], 'trip_cap': 400}, [5, 1070]), ({'reads': [[16, 4, 'S'], [26, 4, 'S'], [123, 3, 'S'], [51, 4, 'S'], [87, 3, 'S'], [118, 4, 'S'], [46, 1, 'S'], [56, 2, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 150, 150, 110, 200, 110], 'trip_cap': 400}, [3, 820])], [({'reads': [[31, 2, 'S'], [61, 0, 'S'], [64, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 150, 200, 200, 150, 110], 'trip_cap': 900}, [2, 310]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[0, 3, 'S'], [45, 2, 'S'], [50, 1, 'S'], [70, 2, 'S'], [100, 2, 'S'], [101, 2, 'S'], [131, 1, 'S'], [132, 1, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 200, 150, 200, 150, 200], 'trip_cap': 900}, [4, 1050]), ({'reads': [[18, 3, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [75, 75, 150, 75, 200, 110], 'trip_cap': 900}, [1, 75]), ({'reads': [[33, 1, 'S'], [118, 1, 'S'], [141, 2, 'S'], [64, 5, 'S'], [84, 5, 'S'], [64, 5, 'S'], [115, 0, 'S'], [121, 5, 'S'], [124, 5, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [200, 110, 200, 200, 150, 75], 'trip_cap': 900}, [3, 920]), ({'reads': [[12, 5, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [150, 110, 110, 150, 75, 110], 'trip_cap': 900}, [1, 110]), ({'reads': [[35, 0, 'N'], [65, 3, 'S'], [68, 3, 'S'], [68, 1, 'S'], [68, 1, 'S'], [99, 4, 'S'], [102, 1, 'N'], [104, 1, 'N'], [122, 5, 'N'], [132, 2, 'S'], [135, 5, 'S'], [136, 4, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 200, 75, 75, 75, 75], 'trip_cap': 400}, [5, 960]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750])], [({'reads': [[26, 2, 'N'], [112, 0, 'N'], [31, 2, 'N'], [28, 2, 'N'], [62, 0, 'N'], [44, 5, 'N'], [25, 5, 'N'], [157, 4, 'N'], [107, 3, 'N'], [41, 5, 'N'], [42, 5, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [200, 75, 150, 110, 110, 150], 'trip_cap': 400}, [3, 820]), ({'reads': [[30, 1, 'N'], [75, 3, 'N'], [78, 0, 'N'], [80, 0, 'N'], [79, 4, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 110, 75, 150, 75, 150], 'trip_cap': 400}, [2, 485]), ({'reads': [[36, 5, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 200, 75, 75, 200, 110], 'trip_cap': 600}, [1, 110]), ({'reads': [[2, 4, 'N'], [32, 3, 'S'], [77, 4, 'N'], [122, 4, 'S'], [124, 4, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 200, 200, 150, 150, 150], 'trip_cap': 900}, [4, 600]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[50, 5, 'N'], [81, 4, 'N'], [84, 4, 'N'], [112, 1, 'N'], [115, 1, 'N'], [115, 2, 'N'], [120, 4, 'S'], [121, 4, 'S'], [122, 4, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [150, 75, 75, 150, 150, 75], 'trip_cap': 900}, [3, 750]), ({'reads': [[37, 5, 'N'], [42, 2, 'N'], [43, 3, 'N'], [46, 3, 'S'], [48, 3, 'S'], [49, 5, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 150, 110, 110, 110, 150], 'trip_cap': 900}, [3, 630])], [({'reads': [[1, 5, 'N'], [3, 5, 'N'], [2, 2, 'N'], [5, 4, 'N'], [8, 4, 'N'], [10, 4, 'N'], [10, 4, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [150, 110, 75, 110, 200, 200], 'trip_cap': 600}, [1, 600]), ({'reads': [[23, 2, 'S'], [26, 1, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 75, 150, 75, 200, 110], 'trip_cap': 900}, [1, 225]), ({'reads': [[24, 0, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 200, 150, 200, 110, 110], 'trip_cap': 900}, [1, 110]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[47, 2, 'S'], [37, 4, 'S'], [7, 1, 'S'], [50, 2, 'S'], [8, 1, 'S'], [77, 4, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [110, 110, 200, 150, 150, 110], 'trip_cap': 900}, [2, 810]), ({'reads': [[94, 4, 'S'], [42, 1, 'S'], [55, 1, 'N'], [89, 1, 'S'], [124, 5, 'S'], [172, 2, 'N'], [45, 2, 'S'], [127, 1, 'S'], [86, 1, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 200, 200, 75, 150, 110], 'trip_cap': 900}, [4, 1460]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[47, 0, 'N'], [48, 0, 'N'], [78, 2, 'N'], [83, 1, 'S'], [84, 4, 'N'], [85, 5, 'N'], [130, 1, 'N'], [161, 0, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 75, 75, 110, 110, 75], 'trip_cap': 900}, [6, 710])]]
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 | [2, 570] | [1, 570] | Failed |
| fee oracle 1 | [2, 750] | [1, 750] | Failed |
| fee oracle 2 | [1, 75] | [1, 75] | Passed |
| fee oracle 3 | [1, 275] | [1, 275] | Passed |
| fee oracle 4 | [3, 555] | [3, 555] | Passed |
| fee oracle 5 | [2, 610] | [1, 600] | Failed |
| fee oracle 6 | [5, 805] | [4, 805] | Failed |
| fee oracle 7 | [2, 350] | [2, 350] | Passed |
SHA-256 / 66106fc831ac5a54f5e10baf30c8bbfc0caac62dbe509be060bc1324e45ce35f
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
reads = sorted(x['reads'])
kept = []
lastg = {}
for t, g, d in reads:
if g in lastg and t - lastg[g] <= x['dedupe']:
continue
lastg[g] = t
kept.append((t, g, d))
trips = []
for t, g, d in kept:
if trips and trips[-1]['d'] == d and t - trips[-1]['t'] <= x['max_gap']:
trips[-1]['g'].append(g)
trips[-1]['t'] = max(trips[-1]['t'], t - x['max_gap'] // 2)
else:
trips.append({'d': d, 't': t, 'g': [g]})
total = sum(min(x['trip_cap'], sum(x['price'][g] for g in tr['g'])) for tr in trips)
return [len(trips), total]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'reads': [[38, 3, 'S'], [41, 3, 'S'], [48, 4, 'S'], [68, 2, 'S'], [78, 0, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [150, 110, 110, 110, 200, 75], 'trip_cap': 900}, [1, 570]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[8, 1, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 75, 75, 150, 75, 150], 'trip_cap': 400}, [1, 75]), ({'reads': [[45, 4, 'S'], [48, 4, 'S'], [48, 3, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 150, 200, 75, 200, 200], 'trip_cap': 900}, [1, 275]), ({'reads': [[39, 2, 'S'], [59, 0, 'S'], [104, 4, 'S'], [114, 3, 'S'], [145, 5, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 75, 110, 110, 150, 110], 'trip_cap': 900}, [3, 555]), ({'reads': [[35, 2, 'S'], [32, 2, 'S'], [12, 5, 'S'], [4, 3, 'S'], [7, 4, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 75, 110, 150, 150, 200], 'trip_cap': 600}, [1, 600]), ({'reads': [[32, 3, 'N'], [87, 5, 'N'], [107, 5, 'N'], [153, 3, 'S'], [2, 4, 'S'], [77, 1, 'N'], [152, 3, 'N'], [89, 5, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 110, 150, 200, 75, 110], 'trip_cap': 600}, [4, 805]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350])], [({'reads': [[132, 4, 'N'], [82, 0, 'N'], [133, 5, 'N'], [72, 2, 'N'], [102, 1, 'N'], [22, 5, 'N'], [27, 3, 'N'], [17, 3, 'N'], [72, 2, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 110, 75, 200, 110, 110], 'trip_cap': 600}, [3, 1025]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[8, 1, 'N'], [203, 3, 'S'], [128, 0, 'S'], [83, 0, 'S'], [175, 1, 'S'], [173, 1, 'S'], [53, 0, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 75, 200, 200, 150, 150], 'trip_cap': 600}, [6, 800]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[38, 0, 'N'], [40, 0, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 110, 200, 75, 150, 150], 'trip_cap': 600}, [1, 200]), ({'reads': [[62, 3, 'N'], [115, 3, 'N'], [64, 0, 'N'], [145, 4, 'N'], [42, 1, 'N'], [64, 3, 'N'], [37, 5, 'N'], [84, 4, 'N'], [114, 1, 'N'], [63, 5, 'N'], [116, 1, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 75, 150, 150, 110, 110], 'trip_cap': 900}, [1, 900]), ({'reads': [[37, 5, 'S'], [67, 2, 'S'], [72, 0, 'S'], [75, 0, 'S'], [103, 1, 'S'], [123, 4, 'S'], [153, 5, 'S'], [184, 4, 'S'], [204, 3, 'S'], [204, 3, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [75, 200, 200, 75, 110, 150], 'trip_cap': 400}, [5, 1070]), ({'reads': [[16, 4, 'S'], [26, 4, 'S'], [123, 3, 'S'], [51, 4, 'S'], [87, 3, 'S'], [118, 4, 'S'], [46, 1, 'S'], [56, 2, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 150, 150, 110, 200, 110], 'trip_cap': 400}, [3, 820])], [({'reads': [[31, 2, 'S'], [61, 0, 'S'], [64, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 150, 200, 200, 150, 110], 'trip_cap': 900}, [2, 310]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[0, 3, 'S'], [45, 2, 'S'], [50, 1, 'S'], [70, 2, 'S'], [100, 2, 'S'], [101, 2, 'S'], [131, 1, 'S'], [132, 1, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 200, 150, 200, 150, 200], 'trip_cap': 900}, [4, 1050]), ({'reads': [[18, 3, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [75, 75, 150, 75, 200, 110], 'trip_cap': 900}, [1, 75]), ({'reads': [[33, 1, 'S'], [118, 1, 'S'], [141, 2, 'S'], [64, 5, 'S'], [84, 5, 'S'], [64, 5, 'S'], [115, 0, 'S'], [121, 5, 'S'], [124, 5, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [200, 110, 200, 200, 150, 75], 'trip_cap': 900}, [3, 920]), ({'reads': [[12, 5, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [150, 110, 110, 150, 75, 110], 'trip_cap': 900}, [1, 110]), ({'reads': [[35, 0, 'N'], [65, 3, 'S'], [68, 3, 'S'], [68, 1, 'S'], [68, 1, 'S'], [99, 4, 'S'], [102, 1, 'N'], [104, 1, 'N'], [122, 5, 'N'], [132, 2, 'S'], [135, 5, 'S'], [136, 4, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 200, 75, 75, 75, 75], 'trip_cap': 400}, [5, 960]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750])], [({'reads': [[26, 2, 'N'], [112, 0, 'N'], [31, 2, 'N'], [28, 2, 'N'], [62, 0, 'N'], [44, 5, 'N'], [25, 5, 'N'], [157, 4, 'N'], [107, 3, 'N'], [41, 5, 'N'], [42, 5, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [200, 75, 150, 110, 110, 150], 'trip_cap': 400}, [3, 820]), ({'reads': [[30, 1, 'N'], [75, 3, 'N'], [78, 0, 'N'], [80, 0, 'N'], [79, 4, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 110, 75, 150, 75, 150], 'trip_cap': 400}, [2, 485]), ({'reads': [[36, 5, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 200, 75, 75, 200, 110], 'trip_cap': 600}, [1, 110]), ({'reads': [[2, 4, 'N'], [32, 3, 'S'], [77, 4, 'N'], [122, 4, 'S'], [124, 4, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 200, 200, 150, 150, 150], 'trip_cap': 900}, [4, 600]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[50, 5, 'N'], [81, 4, 'N'], [84, 4, 'N'], [112, 1, 'N'], [115, 1, 'N'], [115, 2, 'N'], [120, 4, 'S'], [121, 4, 'S'], [122, 4, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [150, 75, 75, 150, 150, 75], 'trip_cap': 900}, [3, 750]), ({'reads': [[37, 5, 'N'], [42, 2, 'N'], [43, 3, 'N'], [46, 3, 'S'], [48, 3, 'S'], [49, 5, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 150, 110, 110, 110, 150], 'trip_cap': 900}, [3, 630])], [({'reads': [[1, 5, 'N'], [3, 5, 'N'], [2, 2, 'N'], [5, 4, 'N'], [8, 4, 'N'], [10, 4, 'N'], [10, 4, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [150, 110, 75, 110, 200, 200], 'trip_cap': 600}, [1, 600]), ({'reads': [[23, 2, 'S'], [26, 1, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 75, 150, 75, 200, 110], 'trip_cap': 900}, [1, 225]), ({'reads': [[24, 0, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 200, 150, 200, 110, 110], 'trip_cap': 900}, [1, 110]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[47, 2, 'S'], [37, 4, 'S'], [7, 1, 'S'], [50, 2, 'S'], [8, 1, 'S'], [77, 4, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [110, 110, 200, 150, 150, 110], 'trip_cap': 900}, [2, 810]), ({'reads': [[94, 4, 'S'], [42, 1, 'S'], [55, 1, 'N'], [89, 1, 'S'], [124, 5, 'S'], [172, 2, 'N'], [45, 2, 'S'], [127, 1, 'S'], [86, 1, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 200, 200, 75, 150, 110], 'trip_cap': 900}, [4, 1460]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[47, 0, 'N'], [48, 0, 'N'], [78, 2, 'N'], [83, 1, 'S'], [84, 4, 'N'], [85, 5, 'N'], [130, 1, 'N'], [161, 0, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 75, 75, 110, 110, 75], 'trip_cap': 900}, [6, 710])]]
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 | [1, 570] | [1, 570] | Passed |
| fee oracle 1 | [2, 750] | [1, 750] | Failed |
| fee oracle 2 | [1, 75] | [1, 75] | Passed |
| fee oracle 3 | [1, 275] | [1, 275] | Passed |
| fee oracle 4 | [3, 555] | [3, 555] | Passed |
| fee oracle 5 | [2, 610] | [1, 600] | Failed |
| fee oracle 6 | [5, 805] | [4, 805] | Failed |
| fee oracle 7 | [2, 350] | [2, 350] | Passed |
SHA-256 / 949aeffefafb25ef808ccc317af32ffe977423b43f7fef0d47356c7cc227dd02
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
reads = sorted(x['reads'])
kept = []
lastg = {}
for t, g, d in reads:
if g in lastg and t - lastg[g] <= x['dedupe']:
continue
lastg[g] = t
kept.append((t, g, d))
trips = []
for t, g, d in kept:
if trips and trips[-1]['d'] == d and t - trips[-1]['t'] <= x['max_gap']:
trips[-1]['g'].append(g)
trips[-1]['t'] = t
else:
trips.append({'d': d, 't': t, 'g': [g]})
total = sum(min(x['trip_cap'], sum(x['price'][g] for g in tr['g'])) for tr in trips)
return [len(trips), total]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'reads': [[38, 3, 'S'], [41, 3, 'S'], [48, 4, 'S'], [68, 2, 'S'], [78, 0, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [150, 110, 110, 110, 200, 75], 'trip_cap': 900}, [1, 570]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[8, 1, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 75, 75, 150, 75, 150], 'trip_cap': 400}, [1, 75]), ({'reads': [[45, 4, 'S'], [48, 4, 'S'], [48, 3, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 150, 200, 75, 200, 200], 'trip_cap': 900}, [1, 275]), ({'reads': [[39, 2, 'S'], [59, 0, 'S'], [104, 4, 'S'], [114, 3, 'S'], [145, 5, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 75, 110, 110, 150, 110], 'trip_cap': 900}, [3, 555]), ({'reads': [[35, 2, 'S'], [32, 2, 'S'], [12, 5, 'S'], [4, 3, 'S'], [7, 4, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 75, 110, 150, 150, 200], 'trip_cap': 600}, [1, 600]), ({'reads': [[32, 3, 'N'], [87, 5, 'N'], [107, 5, 'N'], [153, 3, 'S'], [2, 4, 'S'], [77, 1, 'N'], [152, 3, 'N'], [89, 5, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 110, 150, 200, 75, 110], 'trip_cap': 600}, [4, 805]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350])], [({'reads': [[132, 4, 'N'], [82, 0, 'N'], [133, 5, 'N'], [72, 2, 'N'], [102, 1, 'N'], [22, 5, 'N'], [27, 3, 'N'], [17, 3, 'N'], [72, 2, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 110, 75, 200, 110, 110], 'trip_cap': 600}, [3, 1025]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[8, 1, 'N'], [203, 3, 'S'], [128, 0, 'S'], [83, 0, 'S'], [175, 1, 'S'], [173, 1, 'S'], [53, 0, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 75, 200, 200, 150, 150], 'trip_cap': 600}, [6, 800]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[38, 0, 'N'], [40, 0, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 110, 200, 75, 150, 150], 'trip_cap': 600}, [1, 200]), ({'reads': [[62, 3, 'N'], [115, 3, 'N'], [64, 0, 'N'], [145, 4, 'N'], [42, 1, 'N'], [64, 3, 'N'], [37, 5, 'N'], [84, 4, 'N'], [114, 1, 'N'], [63, 5, 'N'], [116, 1, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 75, 150, 150, 110, 110], 'trip_cap': 900}, [1, 900]), ({'reads': [[37, 5, 'S'], [67, 2, 'S'], [72, 0, 'S'], [75, 0, 'S'], [103, 1, 'S'], [123, 4, 'S'], [153, 5, 'S'], [184, 4, 'S'], [204, 3, 'S'], [204, 3, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [75, 200, 200, 75, 110, 150], 'trip_cap': 400}, [5, 1070]), ({'reads': [[16, 4, 'S'], [26, 4, 'S'], [123, 3, 'S'], [51, 4, 'S'], [87, 3, 'S'], [118, 4, 'S'], [46, 1, 'S'], [56, 2, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 150, 150, 110, 200, 110], 'trip_cap': 400}, [3, 820])], [({'reads': [[31, 2, 'S'], [61, 0, 'S'], [64, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 150, 200, 200, 150, 110], 'trip_cap': 900}, [2, 310]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[0, 3, 'S'], [45, 2, 'S'], [50, 1, 'S'], [70, 2, 'S'], [100, 2, 'S'], [101, 2, 'S'], [131, 1, 'S'], [132, 1, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 200, 150, 200, 150, 200], 'trip_cap': 900}, [4, 1050]), ({'reads': [[18, 3, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [75, 75, 150, 75, 200, 110], 'trip_cap': 900}, [1, 75]), ({'reads': [[33, 1, 'S'], [118, 1, 'S'], [141, 2, 'S'], [64, 5, 'S'], [84, 5, 'S'], [64, 5, 'S'], [115, 0, 'S'], [121, 5, 'S'], [124, 5, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [200, 110, 200, 200, 150, 75], 'trip_cap': 900}, [3, 920]), ({'reads': [[12, 5, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [150, 110, 110, 150, 75, 110], 'trip_cap': 900}, [1, 110]), ({'reads': [[35, 0, 'N'], [65, 3, 'S'], [68, 3, 'S'], [68, 1, 'S'], [68, 1, 'S'], [99, 4, 'S'], [102, 1, 'N'], [104, 1, 'N'], [122, 5, 'N'], [132, 2, 'S'], [135, 5, 'S'], [136, 4, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 200, 75, 75, 75, 75], 'trip_cap': 400}, [5, 960]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750])], [({'reads': [[26, 2, 'N'], [112, 0, 'N'], [31, 2, 'N'], [28, 2, 'N'], [62, 0, 'N'], [44, 5, 'N'], [25, 5, 'N'], [157, 4, 'N'], [107, 3, 'N'], [41, 5, 'N'], [42, 5, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [200, 75, 150, 110, 110, 150], 'trip_cap': 400}, [3, 820]), ({'reads': [[30, 1, 'N'], [75, 3, 'N'], [78, 0, 'N'], [80, 0, 'N'], [79, 4, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 110, 75, 150, 75, 150], 'trip_cap': 400}, [2, 485]), ({'reads': [[36, 5, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 200, 75, 75, 200, 110], 'trip_cap': 600}, [1, 110]), ({'reads': [[2, 4, 'N'], [32, 3, 'S'], [77, 4, 'N'], [122, 4, 'S'], [124, 4, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [75, 200, 200, 150, 150, 150], 'trip_cap': 900}, [4, 600]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[50, 5, 'N'], [81, 4, 'N'], [84, 4, 'N'], [112, 1, 'N'], [115, 1, 'N'], [115, 2, 'N'], [120, 4, 'S'], [121, 4, 'S'], [122, 4, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [150, 75, 75, 150, 150, 75], 'trip_cap': 900}, [3, 750]), ({'reads': [[37, 5, 'N'], [42, 2, 'N'], [43, 3, 'N'], [46, 3, 'S'], [48, 3, 'S'], [49, 5, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 150, 110, 110, 110, 150], 'trip_cap': 900}, [3, 630])], [({'reads': [[1, 5, 'N'], [3, 5, 'N'], [2, 2, 'N'], [5, 4, 'N'], [8, 4, 'N'], [10, 4, 'N'], [10, 4, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [150, 110, 75, 110, 200, 200], 'trip_cap': 600}, [1, 600]), ({'reads': [[23, 2, 'S'], [26, 1, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [150, 75, 150, 75, 200, 110], 'trip_cap': 900}, [1, 225]), ({'reads': [[24, 0, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 200, 150, 200, 110, 110], 'trip_cap': 900}, [1, 110]), ({'reads': [[0, 1, 'N'], [2, 1, 'N'], [4, 1, 'N'], [30, 2, 'N'], [55, 3, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 900}, [1, 750]), ({'reads': [[47, 2, 'S'], [37, 4, 'S'], [7, 1, 'S'], [50, 2, 'S'], [8, 1, 'S'], [77, 4, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [110, 110, 200, 150, 150, 110], 'trip_cap': 900}, [2, 810]), ({'reads': [[94, 4, 'S'], [42, 1, 'S'], [55, 1, 'N'], [89, 1, 'S'], [124, 5, 'S'], [172, 2, 'N'], [45, 2, 'S'], [127, 1, 'S'], [86, 1, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 200, 200, 75, 150, 110], 'trip_cap': 900}, [4, 1460]), ({'reads': [[10, 0, 'S'], [5, 4, 'N'], [12, 1, 'S'], [11, 0, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [100, 150, 200, 250, 100, 100], 'trip_cap': 400}, [2, 350]), ({'reads': [[47, 0, 'N'], [48, 0, 'N'], [78, 2, 'N'], [83, 1, 'S'], [84, 4, 'N'], [85, 5, 'N'], [130, 1, 'N'], [161, 0, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 75, 75, 110, 110, 75], 'trip_cap': 900}, [6, 710])]]
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 | [1, 570] | [1, 570] | Passed |
| fee oracle 1 | [1, 750] | [1, 750] | Passed |
| fee oracle 2 | [1, 75] | [1, 75] | Passed |
| fee oracle 3 | [1, 275] | [1, 275] | Passed |
| fee oracle 4 | [3, 555] | [3, 555] | Passed |
| fee oracle 5 | [1, 600] | [1, 600] | Passed |
| fee oracle 6 | [4, 805] | [4, 805] | Passed |
| fee oracle 7 | [2, 350] | [2, 350] | Passed |
SHA-256 / d6a1593d198e51115ff3b27ceb0796e08b7d1ce8b37e9336ab9150a2c55c5a52
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:04.973514+00:00.
Case digest / fb0e3f20f04a75c7f57ca8fb823633faccfa961330e1a726e8133351188f7c08