FA-85716 / Ride-hailing fare and surge pricing / Open access
Cash step applied before currency conversion · case 01
Francs paid in cash come out at odd centimes after conversion.
ROOT CAUSE
Rounding happens in the fare currency before converting.
VERIFIED REPAIR
Convert first, then round to the payment currency cash step.
Unsuccessful approach: Hard-coding a 5-unit step after conversion ignores the payment currency step and double-rounds.
Case contract
Convert a fare to the payment currency with the directed rate fx[FROM+TO] = [num, den] (half up), then, for cash payments only, round half up to the payment currency cash step (CHF 5 centimes, SEK 100 ore, others 1). Card and wallet payments are not cash-rounded. Return the amount in minor units of the payment currency.
Why this case matters
Ride-hailing prices are computed per trip at scale; ordering, unit and boundary slips become systematic over- or under-charging.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(fare_cents, fare_ccy, pay_ccy, method, fx, cash_step):
amt = fare_cents
if method == 'cash':
step = cash_step.get(pay_ccy, 1)
amt = (amt * 2 + step) // (2 * step) * step
if pay_ccy != fare_ccy:
num, den = fx[fare_ccy + pay_ccy]
amt = (amt * num * 2 + den) // (2 * den)
return amt
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: convert before rounding',
[1999, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
22900),
('partial repair probe: convert before rounding',
[3492, 'CHF', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
3632),
('second regression',
[1003, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
11500),
('normal control 1',
[1600, 'SEK', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
144),
('normal control 2',
[885, 'CHF', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
920),
('normal control 3',
[2502, 'EUR', 'CHF', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2352),
('normal control 4',
[1999, 'CHF', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2079)],
[('regression: convert before rounding',
[1003, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
11500),
('partial repair probe: convert before rounding',
[3472, 'SEK', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
312),
('second regression',
[2573, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2420),
('normal control 1',
[788, 'EUR', 'CHF', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
741),
('normal control 2',
[2502, 'CHF', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2602),
('normal control 3',
[1999, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1999),
('normal control 4',
[1999, 'SEK', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
180)],
[('regression: convert before rounding',
[1234, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1160),
('partial repair probe: convert before rounding',
[1234, 'SEK', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
111),
('second regression',
[1999, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
22900),
('normal control 1',
[1566, 'CHF', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1565),
('normal control 2',
[1234, 'CHF', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1235),
('normal control 3',
[1003, 'SEK', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
90),
('normal control 4',
[1003, 'EUR', 'CHF', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
943)],
[('regression: convert before rounding',
[1234, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1160),
('partial repair probe: convert before rounding',
[2502, 'CHF', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2602),
('second regression',
[1451, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1365),
('normal control 1',
[1003, 'CHF', 'CHF', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1003),
('normal control 2',
[1934, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1934),
('normal control 3',
[1999, 'CHF', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2079),
('normal control 4',
[1531, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1531)],
[('regression: convert before rounding',
[1234, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
14200),
('partial repair probe: convert before rounding',
[1003, 'CHF', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1043),
('second regression',
[1999, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
22900),
('normal control 1',
[1999, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1999),
('normal control 2',
[1003, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1003),
('normal control 3',
[2630, 'SEK', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
237),
('normal control 4',
[2489, 'SEK', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
224)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: convert before rounding | 22940 | 22900 | Failed |
| partial repair probe: convert before rounding | 3632 | 3632 | Passed |
| second regression | 11470 | 11500 | Failed |
| normal control 1 | 144 | 144 | Passed |
| normal control 2 | 920 | 920 | Passed |
| normal control 3 | 2352 | 2352 | Passed |
| normal control 4 | 2079 | 2079 | Passed |
SHA-256 / 5202bd0a1deb807eb55ced44e42ff5aa0070d4836110f97faeb48c7490a22070
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(fare_cents, fare_ccy, pay_ccy, method, fx, cash_step):
amt = fare_cents
if pay_ccy != fare_ccy:
num, den = fx[fare_ccy + pay_ccy]
amt = (amt * num * 2 + den) // (2 * den)
amt = (amt * 2 + 5) // 10 * 5 if method == 'cash' else amt
if method == 'cash':
step = cash_step.get(pay_ccy, 1)
amt = (amt * 2 + step) // (2 * step) * step
return amt
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: convert before rounding',
[1999, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
22900),
('partial repair probe: convert before rounding',
[3492, 'CHF', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
3632),
('second regression',
[1003, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
11500),
('normal control 1',
[1600, 'SEK', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
144),
('normal control 2',
[885, 'CHF', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
920),
('normal control 3',
[2502, 'EUR', 'CHF', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2352),
('normal control 4',
[1999, 'CHF', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2079)],
[('regression: convert before rounding',
[1003, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
11500),
('partial repair probe: convert before rounding',
[3472, 'SEK', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
312),
('second regression',
[2573, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2420),
('normal control 1',
[788, 'EUR', 'CHF', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
741),
('normal control 2',
[2502, 'CHF', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2602),
('normal control 3',
[1999, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1999),
('normal control 4',
[1999, 'SEK', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
180)],
[('regression: convert before rounding',
[1234, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1160),
('partial repair probe: convert before rounding',
[1234, 'SEK', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
111),
('second regression',
[1999, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
22900),
('normal control 1',
[1566, 'CHF', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1565),
('normal control 2',
[1234, 'CHF', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1235),
('normal control 3',
[1003, 'SEK', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
90),
('normal control 4',
[1003, 'EUR', 'CHF', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
943)],
[('regression: convert before rounding',
[1234, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1160),
('partial repair probe: convert before rounding',
[2502, 'CHF', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2602),
('second regression',
[1451, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1365),
('normal control 1',
[1003, 'CHF', 'CHF', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1003),
('normal control 2',
[1934, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1934),
('normal control 3',
[1999, 'CHF', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2079),
('normal control 4',
[1531, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1531)],
[('regression: convert before rounding',
[1234, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
14200),
('partial repair probe: convert before rounding',
[1003, 'CHF', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1043),
('second regression',
[1999, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
22900),
('normal control 1',
[1999, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1999),
('normal control 2',
[1003, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1003),
('normal control 3',
[2630, 'SEK', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
237),
('normal control 4',
[2489, 'SEK', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
224)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: convert before rounding | 22900 | 22900 | Passed |
| partial repair probe: convert before rounding | 3630 | 3632 | Failed |
| second regression | 11500 | 11500 | Passed |
| normal control 1 | 144 | 144 | Passed |
| normal control 2 | 920 | 920 | Passed |
| normal control 3 | 2352 | 2352 | Passed |
| normal control 4 | 2079 | 2079 | Passed |
SHA-256 / aab906411fa43c6801ff433910fe60559cc08009ac118edc9e69dcffe4351b76
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(fare_cents, fare_ccy, pay_ccy, method, fx, cash_step):
amt = fare_cents
if pay_ccy != fare_ccy:
num, den = fx[fare_ccy + pay_ccy]
amt = (amt * num * 2 + den) // (2 * den)
if method == 'cash':
step = cash_step.get(pay_ccy, 1)
amt = (amt * 2 + step) // (2 * step) * step
return amt
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: convert before rounding',
[1999, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
22900),
('partial repair probe: convert before rounding',
[3492, 'CHF', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
3632),
('second regression',
[1003, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
11500),
('normal control 1',
[1600, 'SEK', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
144),
('normal control 2',
[885, 'CHF', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
920),
('normal control 3',
[2502, 'EUR', 'CHF', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2352),
('normal control 4',
[1999, 'CHF', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2079)],
[('regression: convert before rounding',
[1003, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
11500),
('partial repair probe: convert before rounding',
[3472, 'SEK', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
312),
('second regression',
[2573, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2420),
('normal control 1',
[788, 'EUR', 'CHF', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
741),
('normal control 2',
[2502, 'CHF', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2602),
('normal control 3',
[1999, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1999),
('normal control 4',
[1999, 'SEK', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
180)],
[('regression: convert before rounding',
[1234, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1160),
('partial repair probe: convert before rounding',
[1234, 'SEK', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
111),
('second regression',
[1999, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
22900),
('normal control 1',
[1566, 'CHF', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1565),
('normal control 2',
[1234, 'CHF', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1235),
('normal control 3',
[1003, 'SEK', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
90),
('normal control 4',
[1003, 'EUR', 'CHF', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
943)],
[('regression: convert before rounding',
[1234, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1160),
('partial repair probe: convert before rounding',
[2502, 'CHF', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2602),
('second regression',
[1451, 'EUR', 'CHF', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1365),
('normal control 1',
[1003, 'CHF', 'CHF', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1003),
('normal control 2',
[1934, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1934),
('normal control 3',
[1999, 'CHF', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
2079),
('normal control 4',
[1531, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1531)],
[('regression: convert before rounding',
[1234, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
14200),
('partial repair probe: convert before rounding',
[1003, 'CHF', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1043),
('second regression',
[1999, 'EUR', 'SEK', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
22900),
('normal control 1',
[1999, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1999),
('normal control 2',
[1003, 'EUR', 'EUR', 'cash',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
1003),
('normal control 3',
[2630, 'SEK', 'EUR', 'card',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
237),
('normal control 4',
[2489, 'SEK', 'EUR', 'wallet',
{'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
{'CHF': 5, 'SEK': 100}],
224)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: convert before rounding | 22900 | 22900 | Passed |
| partial repair probe: convert before rounding | 3632 | 3632 | Passed |
| second regression | 11500 | 11500 | Passed |
| normal control 1 | 144 | 144 | Passed |
| normal control 2 | 920 | 920 | Passed |
| normal control 3 | 2352 | 2352 | Passed |
| normal control 4 | 2079 | 2079 | Passed |
SHA-256 / d1bd6ce02d4152338651888b99f03b3f49e46465a249c0c7971bbf6cb0a17f65
Verification & scope
A deterministic toy pricing contract stipulated for this example; it does not reproduce the pricing of any real ride-hailing operator or regulator. 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:50:42.919476+00:00.
Case digest / a2ab18a5b789b2f35d5da87a180f0707c47e2d90e6903318c112a5b5ac46f9dd