FAILURE MAP
← Case archive

FA-68726 / Toll and parking fee computation / Open access

Open-road gantry trip building: dropped duplicates re-anchor the duplicate window · case 01

Open-road gantry trip building returns a wrong result when dropped duplicates re-anchor the duplicate window.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The duplicate anchor never advances past the first read, so later genuine passages of the gantry are dropped.

VERIFIED REPAIR

Restore the duplicate anchor rule so that the step reads `lastg[g] = t kept.append((t, g, d))`.

Unsuccessful approach: Anchoring one minute early widens every duplicate window by a minute.

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
        kept.append((t, g, d))
        lastg[g] = t if g not in lastg else lastg[g]
    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': [[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': [[6, 1, 'S'], [26, 1, 'S'], [71, 0, 'S'], [73, 0, 'S'], [74, 0, 'S'], [94, 3, 'S'], [95, 3, 'S'], [114, 3, 'S'], [115, 3, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [150, 200, 110, 150, 150, 200], 'trip_cap': 900}, [2, 1000]), ({'reads': [[8, 4, 'S'], [11, 4, 'S'], [39, 4, 'S'], [84, 0, 'S'], [87, 4, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 150, 110, 150, 75, 110], 'trip_cap': 900}, [3, 335]), ({'reads': [[28, 0, 'S'], [29, 2, 'N'], [39, 2, 'S'], [40, 2, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [75, 200, 200, 75, 200, 200], 'trip_cap': 900}, [3, 475]), ({'reads': [[26, 0, 'N'], [29, 5, 'N'], [34, 0, 'S'], [39, 0, 'S'], [42, 0, 'S'], [44, 5, 'S'], [74, 0, 'S'], [74, 0, 'S'], [104, 2, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [75, 150, 200, 75, 75, 75], 'trip_cap': 600}, [4, 725]), ({'reads': [[10, 5, 'N'], [11, 5, 'N'], [15, 0, 'S'], [16, 0, 'S'], [47, 5, 'S'], [78, 3, 'S'], [109, 1, 'N'], [110, 0, 'N'], [141, 2, 'N'], [161, 1, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 110, 110, 110, 150, 75], 'trip_cap': 900}, [7, 990]), ({'reads': [[26, 4, 'N'], [57, 4, 'N'], [58, 0, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 150, 75, 150, 75, 75], 'trip_cap': 600}, [2, 260])], [({'reads': [[44, 0, 'S'], [46, 0, 'S'], [89, 1, 'N'], [134, 0, 'N'], [154, 3, 'N'], [156, 3, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 150, 110, 200, 200, 200], 'trip_cap': 900}, [3, 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': [[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': [[4, 5, 'S'], [5, 5, 'S'], [34, 3, 'N'], [35, 2, 'N'], [36, 4, 'S'], [38, 4, 'S'], [81, 5, 'N'], [82, 2, 'N'], [85, 2, 'N'], [85, 3, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 110, 75, 110, 200, 75], 'trip_cap': 600}, [4, 720]), ({'reads': [[9, 3, 'S'], [39, 5, 'S'], [69, 2, 'S'], [99, 1, 'N'], [119, 1, 'N'], [124, 5, 'N'], [129, 2, 'N'], [130, 2, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 110, 150, 110, 75, 150], 'trip_cap': 600}, [2, 930]), ({'reads': [[11, 2, 'N'], [14, 4, 'S'], [15, 4, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 110, 75, 200, 75, 75], 'trip_cap': 600}, [2, 150]), ({'reads': [[15, 4, 'S'], [20, 2, 'S'], [50, 0, 'S'], [50, 0, 'S'], [81, 5, 'S'], [101, 5, 'S'], [102, 2, 'S'], [107, 0, 'S'], [127, 4, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 150, 75, 200, 75, 75], 'trip_cap': 400}, [4, 750]), ({'reads': [[34, 5, 'S'], [35, 5, 'S'], [79, 2, 'S'], [110, 2, 'S'], [111, 2, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 200, 75, 150, 150, 110], 'trip_cap': 400}, [3, 260])], [({'reads': [[157, 4, 'S'], [126, 4, 'S'], [93, 5, 'S'], [177, 3, 'S'], [60, 0, 'N'], [90, 1, 'S'], [123, 5, 'S'], [92, 1, 'S'], [124, 5, 'S'], [29, 0, 'S'], [128, 4, 'S'], [24, 4, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 75, 110, 75, 75, 200], 'trip_cap': 600}, [4, 1175]), ({'reads': [[13, 2, 'S'], [16, 3, 'S'], [17, 3, 'S'], [26, 0, 'S'], [26, 0, 'S'], [36, 5, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 75, 75, 150, 75, 110], 'trip_cap': 600}, [1, 410]), ({'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': [[15, 3, 'N'], [45, 1, 'N'], [45, 1, 'N'], [50, 0, 'N'], [95, 5, 'S'], [105, 3, 'S'], [135, 3, 'S'], [138, 3, 'S'], [136, 3, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 75, 75, 200, 110, 110], 'trip_cap': 900}, [2, 1185]), ({'reads': [[16, 2, 'N'], [36, 2, 'S'], [67, 5, 'S'], [68, 3, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 110, 150, 75, 200, 200], 'trip_cap': 600}, [3, 575]), ({'reads': [[36, 1, 'S'], [37, 2, 'S'], [40, 3, 'S'], [45, 1, 'S'], [50, 0, 'N'], [95, 3, 'N'], [126, 1, 'N'], [127, 1, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 110, 75, 150, 150, 200], 'trip_cap': 600}, [4, 815]), ({'reads': [[18, 3, 'N'], [20, 3, 'N'], [38, 5, 'N'], [69, 3, 'N'], [99, 2, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 150, 75, 110, 150, 200], 'trip_cap': 400}, [2, 495]), ({'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': [[32, 5, 'N'], [35, 0, 'N'], [35, 0, 'N'], [66, 1, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [110, 200, 110, 110, 200, 200], 'trip_cap': 600}, [2, 510]), ({'reads': [[40, 0, 'N'], [70, 2, 'N'], [75, 2, 'N'], [85, 5, 'N'], [88, 2, 'N'], [98, 1, 'N'], [108, 1, 'N'], [110, 1, 'N'], [113, 0, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [75, 110, 150, 200, 200, 150], 'trip_cap': 900}, [2, 970]), ({'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': [[197, 1, 'S'], [149, 5, 'N'], [56, 1, 'N'], [11, 1, 'N'], [101, 5, 'N'], [8, 5, 'N'], [166, 2, 'N'], [146, 5, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 110, 200, 150, 200, 110], 'trip_cap': 900}, [5, 860]), ({'reads': [[15, 5, 'N'], [145, 4, 'S'], [114, 3, 'N'], [35, 1, 'N'], [80, 2, 'N'], [101, 1, 'S'], [100, 1, 'N'], [38, 1, 'N'], [102, 1, 'S'], [111, 1, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 110, 150, 150, 150, 200], 'trip_cap': 600}, [5, 1090]), ({'reads': [[19, 1, 'S'], [64, 0, 'S'], [94, 4, 'S'], [96, 4, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [200, 150, 75, 200, 110, 75], 'trip_cap': 900}, [3, 460]), ({'reads': [[30, 1, 'N'], [81, 2, 'S'], [111, 5, 'S'], [30, 1, 'N'], [61, 0, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 200, 75, 110, 110, 110], 'trip_cap': 400}, [3, 495])], [({'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': [[33, 4, 'N'], [63, 4, 'N'], [94, 2, 'N'], [125, 1, 'N'], [170, 5, 'N'], [173, 5, 'N'], [180, 3, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 200, 200, 200, 150, 200], 'trip_cap': 900}, [4, 1100]), ({'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': [[66, 1, 'S'], [43, 0, 'S'], [46, 5, 'S'], [76, 0, 'S'], [71, 3, 'S'], [13, 3, 'S'], [14, 3, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 150, 200, 75, 150, 200], 'trip_cap': 900}, [1, 900]), ({'reads': [[16, 4, 'N'], [47, 3, 'N'], [48, 3, 'N'], [77, 4, 'N'], [77, 4, 'N'], [108, 3, 'N'], [110, 3, 'N'], [139, 5, 'N'], [149, 2, 'N'], [159, 3, 'N'], [190, 2, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 75, 75, 200, 150, 150], 'trip_cap': 400}, [5, 1175]), ({'reads': [[50, 4, 'S'], [55, 0, 'S'], [56, 0, 'S'], [58, 4, 'S'], [59, 4, 'S'], [68, 2, 'S'], [70, 2, 'S'], [98, 0, 'S'], [143, 0, 'S'], [145, 0, 'S'], [188, 2, 'S'], [218, 4, 'N'], [223, 2, 'N'], [226, 2, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 150, 200, 150, 200, 200], 'trip_cap': 600}, [4, 1475]), ({'reads': [[28, 0, 'S'], [73, 0, 'N'], [83, 3, 'N'], [85, 3, 'N'], [84, 5, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 110, 150, 110, 75, 75], 'trip_cap': 600}, [3, 485]), ({'reads': [[50, 5, 'N'], [52, 5, 'N'], [53, 5, 'N'], [63, 2, 'N'], [66, 2, 'N'], [108, 2, 'N'], [110, 2, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 200, 200, 110, 150, 200], 'trip_cap': 600}, [2, 800])]]
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 fixtureActualExpectedOutcome
fee oracle 0[2, 350][2, 350]Passed
fee oracle 1[1, 750][1, 750]Passed
fee oracle 2[2, 1150][2, 1000]Failed
fee oracle 3[3, 335][3, 335]Passed
fee oracle 4[3, 675][3, 475]Failed
fee oracle 5[4, 800][4, 725]Failed
fee oracle 6[7, 990][7, 990]Passed
fee oracle 7[2, 260][2, 260]Passed

SHA-256 / 84c6cc38f001aef697c802d3948161919cda2ba0fe4fee7184d1d013be9bc813

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 - 1
        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': [[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': [[6, 1, 'S'], [26, 1, 'S'], [71, 0, 'S'], [73, 0, 'S'], [74, 0, 'S'], [94, 3, 'S'], [95, 3, 'S'], [114, 3, 'S'], [115, 3, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [150, 200, 110, 150, 150, 200], 'trip_cap': 900}, [2, 1000]), ({'reads': [[8, 4, 'S'], [11, 4, 'S'], [39, 4, 'S'], [84, 0, 'S'], [87, 4, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 150, 110, 150, 75, 110], 'trip_cap': 900}, [3, 335]), ({'reads': [[28, 0, 'S'], [29, 2, 'N'], [39, 2, 'S'], [40, 2, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [75, 200, 200, 75, 200, 200], 'trip_cap': 900}, [3, 475]), ({'reads': [[26, 0, 'N'], [29, 5, 'N'], [34, 0, 'S'], [39, 0, 'S'], [42, 0, 'S'], [44, 5, 'S'], [74, 0, 'S'], [74, 0, 'S'], [104, 2, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [75, 150, 200, 75, 75, 75], 'trip_cap': 600}, [4, 725]), ({'reads': [[10, 5, 'N'], [11, 5, 'N'], [15, 0, 'S'], [16, 0, 'S'], [47, 5, 'S'], [78, 3, 'S'], [109, 1, 'N'], [110, 0, 'N'], [141, 2, 'N'], [161, 1, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 110, 110, 110, 150, 75], 'trip_cap': 900}, [7, 990]), ({'reads': [[26, 4, 'N'], [57, 4, 'N'], [58, 0, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 150, 75, 150, 75, 75], 'trip_cap': 600}, [2, 260])], [({'reads': [[44, 0, 'S'], [46, 0, 'S'], [89, 1, 'N'], [134, 0, 'N'], [154, 3, 'N'], [156, 3, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 150, 110, 200, 200, 200], 'trip_cap': 900}, [3, 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': [[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': [[4, 5, 'S'], [5, 5, 'S'], [34, 3, 'N'], [35, 2, 'N'], [36, 4, 'S'], [38, 4, 'S'], [81, 5, 'N'], [82, 2, 'N'], [85, 2, 'N'], [85, 3, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 110, 75, 110, 200, 75], 'trip_cap': 600}, [4, 720]), ({'reads': [[9, 3, 'S'], [39, 5, 'S'], [69, 2, 'S'], [99, 1, 'N'], [119, 1, 'N'], [124, 5, 'N'], [129, 2, 'N'], [130, 2, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 110, 150, 110, 75, 150], 'trip_cap': 600}, [2, 930]), ({'reads': [[11, 2, 'N'], [14, 4, 'S'], [15, 4, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 110, 75, 200, 75, 75], 'trip_cap': 600}, [2, 150]), ({'reads': [[15, 4, 'S'], [20, 2, 'S'], [50, 0, 'S'], [50, 0, 'S'], [81, 5, 'S'], [101, 5, 'S'], [102, 2, 'S'], [107, 0, 'S'], [127, 4, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 150, 75, 200, 75, 75], 'trip_cap': 400}, [4, 750]), ({'reads': [[34, 5, 'S'], [35, 5, 'S'], [79, 2, 'S'], [110, 2, 'S'], [111, 2, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 200, 75, 150, 150, 110], 'trip_cap': 400}, [3, 260])], [({'reads': [[157, 4, 'S'], [126, 4, 'S'], [93, 5, 'S'], [177, 3, 'S'], [60, 0, 'N'], [90, 1, 'S'], [123, 5, 'S'], [92, 1, 'S'], [124, 5, 'S'], [29, 0, 'S'], [128, 4, 'S'], [24, 4, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 75, 110, 75, 75, 200], 'trip_cap': 600}, [4, 1175]), ({'reads': [[13, 2, 'S'], [16, 3, 'S'], [17, 3, 'S'], [26, 0, 'S'], [26, 0, 'S'], [36, 5, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 75, 75, 150, 75, 110], 'trip_cap': 600}, [1, 410]), ({'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': [[15, 3, 'N'], [45, 1, 'N'], [45, 1, 'N'], [50, 0, 'N'], [95, 5, 'S'], [105, 3, 'S'], [135, 3, 'S'], [138, 3, 'S'], [136, 3, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 75, 75, 200, 110, 110], 'trip_cap': 900}, [2, 1185]), ({'reads': [[16, 2, 'N'], [36, 2, 'S'], [67, 5, 'S'], [68, 3, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 110, 150, 75, 200, 200], 'trip_cap': 600}, [3, 575]), ({'reads': [[36, 1, 'S'], [37, 2, 'S'], [40, 3, 'S'], [45, 1, 'S'], [50, 0, 'N'], [95, 3, 'N'], [126, 1, 'N'], [127, 1, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 110, 75, 150, 150, 200], 'trip_cap': 600}, [4, 815]), ({'reads': [[18, 3, 'N'], [20, 3, 'N'], [38, 5, 'N'], [69, 3, 'N'], [99, 2, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 150, 75, 110, 150, 200], 'trip_cap': 400}, [2, 495]), ({'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': [[32, 5, 'N'], [35, 0, 'N'], [35, 0, 'N'], [66, 1, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [110, 200, 110, 110, 200, 200], 'trip_cap': 600}, [2, 510]), ({'reads': [[40, 0, 'N'], [70, 2, 'N'], [75, 2, 'N'], [85, 5, 'N'], [88, 2, 'N'], [98, 1, 'N'], [108, 1, 'N'], [110, 1, 'N'], [113, 0, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [75, 110, 150, 200, 200, 150], 'trip_cap': 900}, [2, 970]), ({'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': [[197, 1, 'S'], [149, 5, 'N'], [56, 1, 'N'], [11, 1, 'N'], [101, 5, 'N'], [8, 5, 'N'], [166, 2, 'N'], [146, 5, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 110, 200, 150, 200, 110], 'trip_cap': 900}, [5, 860]), ({'reads': [[15, 5, 'N'], [145, 4, 'S'], [114, 3, 'N'], [35, 1, 'N'], [80, 2, 'N'], [101, 1, 'S'], [100, 1, 'N'], [38, 1, 'N'], [102, 1, 'S'], [111, 1, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 110, 150, 150, 150, 200], 'trip_cap': 600}, [5, 1090]), ({'reads': [[19, 1, 'S'], [64, 0, 'S'], [94, 4, 'S'], [96, 4, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [200, 150, 75, 200, 110, 75], 'trip_cap': 900}, [3, 460]), ({'reads': [[30, 1, 'N'], [81, 2, 'S'], [111, 5, 'S'], [30, 1, 'N'], [61, 0, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 200, 75, 110, 110, 110], 'trip_cap': 400}, [3, 495])], [({'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': [[33, 4, 'N'], [63, 4, 'N'], [94, 2, 'N'], [125, 1, 'N'], [170, 5, 'N'], [173, 5, 'N'], [180, 3, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 200, 200, 200, 150, 200], 'trip_cap': 900}, [4, 1100]), ({'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': [[66, 1, 'S'], [43, 0, 'S'], [46, 5, 'S'], [76, 0, 'S'], [71, 3, 'S'], [13, 3, 'S'], [14, 3, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 150, 200, 75, 150, 200], 'trip_cap': 900}, [1, 900]), ({'reads': [[16, 4, 'N'], [47, 3, 'N'], [48, 3, 'N'], [77, 4, 'N'], [77, 4, 'N'], [108, 3, 'N'], [110, 3, 'N'], [139, 5, 'N'], [149, 2, 'N'], [159, 3, 'N'], [190, 2, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 75, 75, 200, 150, 150], 'trip_cap': 400}, [5, 1175]), ({'reads': [[50, 4, 'S'], [55, 0, 'S'], [56, 0, 'S'], [58, 4, 'S'], [59, 4, 'S'], [68, 2, 'S'], [70, 2, 'S'], [98, 0, 'S'], [143, 0, 'S'], [145, 0, 'S'], [188, 2, 'S'], [218, 4, 'N'], [223, 2, 'N'], [226, 2, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 150, 200, 150, 200, 200], 'trip_cap': 600}, [4, 1475]), ({'reads': [[28, 0, 'S'], [73, 0, 'N'], [83, 3, 'N'], [85, 3, 'N'], [84, 5, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 110, 150, 110, 75, 75], 'trip_cap': 600}, [3, 485]), ({'reads': [[50, 5, 'N'], [52, 5, 'N'], [53, 5, 'N'], [63, 2, 'N'], [66, 2, 'N'], [108, 2, 'N'], [110, 2, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 200, 200, 110, 150, 200], 'trip_cap': 600}, [2, 800])]]
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 fixtureActualExpectedOutcome
fee oracle 0[2, 350][2, 350]Passed
fee oracle 1[1, 900][1, 750]Failed
fee oracle 2[2, 1000][2, 1000]Passed
fee oracle 3[2, 410][3, 335]Failed
fee oracle 4[3, 475][3, 475]Passed
fee oracle 5[4, 725][4, 725]Passed
fee oracle 6[7, 990][7, 990]Passed
fee oracle 7[2, 260][2, 260]Passed

SHA-256 / d0d6604ce141c994e5ade73c26b408a4fa20179e44c3e7a9a94edbd94b1f435f

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': [[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': [[6, 1, 'S'], [26, 1, 'S'], [71, 0, 'S'], [73, 0, 'S'], [74, 0, 'S'], [94, 3, 'S'], [95, 3, 'S'], [114, 3, 'S'], [115, 3, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [150, 200, 110, 150, 150, 200], 'trip_cap': 900}, [2, 1000]), ({'reads': [[8, 4, 'S'], [11, 4, 'S'], [39, 4, 'S'], [84, 0, 'S'], [87, 4, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 150, 110, 150, 75, 110], 'trip_cap': 900}, [3, 335]), ({'reads': [[28, 0, 'S'], [29, 2, 'N'], [39, 2, 'S'], [40, 2, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [75, 200, 200, 75, 200, 200], 'trip_cap': 900}, [3, 475]), ({'reads': [[26, 0, 'N'], [29, 5, 'N'], [34, 0, 'S'], [39, 0, 'S'], [42, 0, 'S'], [44, 5, 'S'], [74, 0, 'S'], [74, 0, 'S'], [104, 2, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [75, 150, 200, 75, 75, 75], 'trip_cap': 600}, [4, 725]), ({'reads': [[10, 5, 'N'], [11, 5, 'N'], [15, 0, 'S'], [16, 0, 'S'], [47, 5, 'S'], [78, 3, 'S'], [109, 1, 'N'], [110, 0, 'N'], [141, 2, 'N'], [161, 1, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 110, 110, 110, 150, 75], 'trip_cap': 900}, [7, 990]), ({'reads': [[26, 4, 'N'], [57, 4, 'N'], [58, 0, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 150, 75, 150, 75, 75], 'trip_cap': 600}, [2, 260])], [({'reads': [[44, 0, 'S'], [46, 0, 'S'], [89, 1, 'N'], [134, 0, 'N'], [154, 3, 'N'], [156, 3, 'N']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 150, 110, 200, 200, 200], 'trip_cap': 900}, [3, 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': [[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': [[4, 5, 'S'], [5, 5, 'S'], [34, 3, 'N'], [35, 2, 'N'], [36, 4, 'S'], [38, 4, 'S'], [81, 5, 'N'], [82, 2, 'N'], [85, 2, 'N'], [85, 3, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 110, 75, 110, 200, 75], 'trip_cap': 600}, [4, 720]), ({'reads': [[9, 3, 'S'], [39, 5, 'S'], [69, 2, 'S'], [99, 1, 'N'], [119, 1, 'N'], [124, 5, 'N'], [129, 2, 'N'], [130, 2, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 110, 150, 110, 75, 150], 'trip_cap': 600}, [2, 930]), ({'reads': [[11, 2, 'N'], [14, 4, 'S'], [15, 4, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 110, 75, 200, 75, 75], 'trip_cap': 600}, [2, 150]), ({'reads': [[15, 4, 'S'], [20, 2, 'S'], [50, 0, 'S'], [50, 0, 'S'], [81, 5, 'S'], [101, 5, 'S'], [102, 2, 'S'], [107, 0, 'S'], [127, 4, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 150, 75, 200, 75, 75], 'trip_cap': 400}, [4, 750]), ({'reads': [[34, 5, 'S'], [35, 5, 'S'], [79, 2, 'S'], [110, 2, 'S'], [111, 2, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 200, 75, 150, 150, 110], 'trip_cap': 400}, [3, 260])], [({'reads': [[157, 4, 'S'], [126, 4, 'S'], [93, 5, 'S'], [177, 3, 'S'], [60, 0, 'N'], [90, 1, 'S'], [123, 5, 'S'], [92, 1, 'S'], [124, 5, 'S'], [29, 0, 'S'], [128, 4, 'S'], [24, 4, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 75, 110, 75, 75, 200], 'trip_cap': 600}, [4, 1175]), ({'reads': [[13, 2, 'S'], [16, 3, 'S'], [17, 3, 'S'], [26, 0, 'S'], [26, 0, 'S'], [36, 5, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 75, 75, 150, 75, 110], 'trip_cap': 600}, [1, 410]), ({'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': [[15, 3, 'N'], [45, 1, 'N'], [45, 1, 'N'], [50, 0, 'N'], [95, 5, 'S'], [105, 3, 'S'], [135, 3, 'S'], [138, 3, 'S'], [136, 3, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 75, 75, 200, 110, 110], 'trip_cap': 900}, [2, 1185]), ({'reads': [[16, 2, 'N'], [36, 2, 'S'], [67, 5, 'S'], [68, 3, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [200, 110, 150, 75, 200, 200], 'trip_cap': 600}, [3, 575]), ({'reads': [[36, 1, 'S'], [37, 2, 'S'], [40, 3, 'S'], [45, 1, 'S'], [50, 0, 'N'], [95, 3, 'N'], [126, 1, 'N'], [127, 1, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [110, 110, 75, 150, 150, 200], 'trip_cap': 600}, [4, 815]), ({'reads': [[18, 3, 'N'], [20, 3, 'N'], [38, 5, 'N'], [69, 3, 'N'], [99, 2, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 150, 75, 110, 150, 200], 'trip_cap': 400}, [2, 495]), ({'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': [[32, 5, 'N'], [35, 0, 'N'], [35, 0, 'N'], [66, 1, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [110, 200, 110, 110, 200, 200], 'trip_cap': 600}, [2, 510]), ({'reads': [[40, 0, 'N'], [70, 2, 'N'], [75, 2, 'N'], [85, 5, 'N'], [88, 2, 'N'], [98, 1, 'N'], [108, 1, 'N'], [110, 1, 'N'], [113, 0, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [75, 110, 150, 200, 200, 150], 'trip_cap': 900}, [2, 970]), ({'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': [[197, 1, 'S'], [149, 5, 'N'], [56, 1, 'N'], [11, 1, 'N'], [101, 5, 'N'], [8, 5, 'N'], [166, 2, 'N'], [146, 5, 'N']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 110, 200, 150, 200, 110], 'trip_cap': 900}, [5, 860]), ({'reads': [[15, 5, 'N'], [145, 4, 'S'], [114, 3, 'N'], [35, 1, 'N'], [80, 2, 'N'], [101, 1, 'S'], [100, 1, 'N'], [38, 1, 'N'], [102, 1, 'S'], [111, 1, 'S']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 110, 150, 150, 150, 200], 'trip_cap': 600}, [5, 1090]), ({'reads': [[19, 1, 'S'], [64, 0, 'S'], [94, 4, 'S'], [96, 4, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [200, 150, 75, 200, 110, 75], 'trip_cap': 900}, [3, 460]), ({'reads': [[30, 1, 'N'], [81, 2, 'S'], [111, 5, 'S'], [30, 1, 'N'], [61, 0, 'S']], 'dedupe': 2, 'max_gap': 20, 'price': [110, 200, 75, 110, 110, 110], 'trip_cap': 400}, [3, 495])], [({'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': [[33, 4, 'N'], [63, 4, 'N'], [94, 2, 'N'], [125, 1, 'N'], [170, 5, 'N'], [173, 5, 'N'], [180, 3, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 200, 200, 200, 150, 200], 'trip_cap': 900}, [4, 1100]), ({'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': [[66, 1, 'S'], [43, 0, 'S'], [46, 5, 'S'], [76, 0, 'S'], [71, 3, 'S'], [13, 3, 'S'], [14, 3, 'S']], 'dedupe': 3, 'max_gap': 30, 'price': [200, 150, 200, 75, 150, 200], 'trip_cap': 900}, [1, 900]), ({'reads': [[16, 4, 'N'], [47, 3, 'N'], [48, 3, 'N'], [77, 4, 'N'], [77, 4, 'N'], [108, 3, 'N'], [110, 3, 'N'], [139, 5, 'N'], [149, 2, 'N'], [159, 3, 'N'], [190, 2, 'N']], 'dedupe': 3, 'max_gap': 30, 'price': [110, 75, 75, 200, 150, 150], 'trip_cap': 400}, [5, 1175]), ({'reads': [[50, 4, 'S'], [55, 0, 'S'], [56, 0, 'S'], [58, 4, 'S'], [59, 4, 'S'], [68, 2, 'S'], [70, 2, 'S'], [98, 0, 'S'], [143, 0, 'S'], [145, 0, 'S'], [188, 2, 'S'], [218, 4, 'N'], [223, 2, 'N'], [226, 2, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 150, 200, 150, 200, 200], 'trip_cap': 600}, [4, 1475]), ({'reads': [[28, 0, 'S'], [73, 0, 'N'], [83, 3, 'N'], [85, 3, 'N'], [84, 5, 'S']], 'dedupe': 3, 'max_gap': 20, 'price': [150, 110, 150, 110, 75, 75], 'trip_cap': 600}, [3, 485]), ({'reads': [[50, 5, 'N'], [52, 5, 'N'], [53, 5, 'N'], [63, 2, 'N'], [66, 2, 'N'], [108, 2, 'N'], [110, 2, 'N']], 'dedupe': 2, 'max_gap': 30, 'price': [75, 200, 200, 110, 150, 200], 'trip_cap': 600}, [2, 800])]]
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 fixtureActualExpectedOutcome
fee oracle 0[2, 350][2, 350]Passed
fee oracle 1[1, 750][1, 750]Passed
fee oracle 2[2, 1000][2, 1000]Passed
fee oracle 3[3, 335][3, 335]Passed
fee oracle 4[3, 475][3, 475]Passed
fee oracle 5[4, 725][4, 725]Passed
fee oracle 6[7, 990][7, 990]Passed
fee oracle 7[2, 260][2, 260]Passed

SHA-256 / afa18777c52943d388b1d0039c38f89bf9c90836f5a79467ac923e1dedc5b8c7

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.885514+00:00.

Case digest / d88cd1f3cde00c35b3bca5e4abd7ba56b9ab6929795990b7b46746b9c249f613