broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(table, pickup_zone, drop_zone, metered, tolls, surge, airport_fees):
    p, d = pickup_zone.upper(), drop_zone.upper()
    flat = table.get(p + '|' + d, table.get(d + '|' + p))
    if flat is not None:
        fare, kind = flat, 'flat'
    else:
        fare, kind = (metered * surge * 2 + 10) // 20, 'metered'
    fare += airport_fees.get(p, {}).get('pickup', 0) + airport_fees.get(d, {}).get('pickup', 0)
    return [fare + tolls, kind]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'AIR', 4387, 250, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5050, 'flat']),
  ('partial repair probe: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'AIR', 2756, 0, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4800, 'flat']),
  ('second regression',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'air', 5529, 600, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5400, 'flat']),
  ('normal control 1',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'AIR', 'MID', 1177, 0, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [2854, 'metered']),
  ('normal control 2',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'Dt', 'DT', 3757, 0, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5636, 'metered']),
  ('normal control 3',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'AIR', 'MID', 3578, 250, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4328, 'metered']),
  ('normal control 4',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'MID', 'DT', 4097, 250, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [6396, 'metered'])],
 [('regression: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'UNI', 'air', 3297, 250, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4450, 'flat']),
  ('partial repair probe: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'Dt', 'AIR', 991, 0, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4800, 'flat']),
  ('second regression',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'air', 4614, 600, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5400, 'flat']),
  ('normal control 1',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'SHUT', 'UNI', 2643, 0, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [2643, 'metered']),
  ('normal control 2',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'Dt', 2569, 0, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5000, 'flat']),
  ('normal control 3',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'SHUT', 'DT', 5450, 0, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [0, 'flat']),
  ('normal control 4',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'AIR', 'SHUT', 4706, 600, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [10512, 'metered'])],
 [('regression: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'MID', 'air', 3585, 600, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [8070, 'metered']),
  ('partial repair probe: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'UNI', 'AIR', 4123, 600, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4800, 'flat']),
  ('second regression',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'UNI', 'AIR', 4026, 600, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4800, 'flat']),
  ('normal control 1',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'Dt', 'DT', 4305, 250, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [8860, 'metered']),
  ('normal control 2',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'MID', 'MID', 2606, 0, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5212, 'metered']),
  ('normal control 3',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'Dt', 4867, 250, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5250, 'flat']),
  ('normal control 4',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'SHUT', 4760, 250, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5510, 'metered'])],
 [('regression: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'SHUT', 'air', 4285, 600, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5185, 'metered']),
  ('partial repair probe: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'AIR', 5437, 250, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5050, 'flat']),
  ('second regression',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'UNI', 'AIR', 1363, 250, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4450, 'flat']),
  ('normal control 1',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'Dt', 'DT', 4478, 600, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [7317, 'metered']),
  ('normal control 2',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'UNI', 5924, 600, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5000, 'flat']),
  ('normal control 3',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'DT', 1853, 250, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5250, 'flat']),
  ('normal control 4',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'Dt', 'MID', 4781, 0, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [7172, 'metered'])],
 [('regression: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'air', 1974, 250, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5050, 'flat']),
  ('partial repair probe: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'MID', 'AIR', 1558, 0, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [2637, 'metered']),
  ('second regression',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'AIR', 2287, 600, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4831, 'metered']),
  ('normal control 1',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'AIR', 'Dt', 2942, 250, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5250, 'flat']),
  ('normal control 2',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'AIR', 'SHUT', 3509, 0, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4009, 'metered']),
  ('normal control 3',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'MID', 'SHUT', 2704, 0, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [2704, 'metered']),
  ('normal control 4',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'SHUT', 'DT', 2888, 0, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [0, 'flat'])]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(table, pickup_zone, drop_zone, metered, tolls, surge, airport_fees):
    p, d = pickup_zone.upper(), drop_zone.upper()
    flat = table.get(p + '|' + d, table.get(d + '|' + p))
    if flat is not None:
        fare, kind = flat, 'flat'
    else:
        fare, kind = (metered * surge * 2 + 10) // 20, 'metered'
    fare += airport_fees.get(p, {}).get('pickup', 0)
    return [fare + tolls, kind]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'AIR', 4387, 250, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5050, 'flat']),
  ('partial repair probe: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'AIR', 2756, 0, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4800, 'flat']),
  ('second regression',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'air', 5529, 600, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5400, 'flat']),
  ('normal control 1',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'AIR', 'MID', 1177, 0, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [2854, 'metered']),
  ('normal control 2',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'Dt', 'DT', 3757, 0, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5636, 'metered']),
  ('normal control 3',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'AIR', 'MID', 3578, 250, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4328, 'metered']),
  ('normal control 4',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'MID', 'DT', 4097, 250, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [6396, 'metered'])],
 [('regression: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'UNI', 'air', 3297, 250, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4450, 'flat']),
  ('partial repair probe: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'Dt', 'AIR', 991, 0, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4800, 'flat']),
  ('second regression',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'air', 4614, 600, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5400, 'flat']),
  ('normal control 1',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'SHUT', 'UNI', 2643, 0, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [2643, 'metered']),
  ('normal control 2',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'Dt', 2569, 0, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5000, 'flat']),
  ('normal control 3',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'SHUT', 'DT', 5450, 0, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [0, 'flat']),
  ('normal control 4',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'AIR', 'SHUT', 4706, 600, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [10512, 'metered'])],
 [('regression: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'MID', 'air', 3585, 600, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [8070, 'metered']),
  ('partial repair probe: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'UNI', 'AIR', 4123, 600, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4800, 'flat']),
  ('second regression',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'UNI', 'AIR', 4026, 600, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4800, 'flat']),
  ('normal control 1',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'Dt', 'DT', 4305, 250, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [8860, 'metered']),
  ('normal control 2',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'MID', 'MID', 2606, 0, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5212, 'metered']),
  ('normal control 3',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'Dt', 4867, 250, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5250, 'flat']),
  ('normal control 4',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'SHUT', 4760, 250, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5510, 'metered'])],
 [('regression: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'SHUT', 'air', 4285, 600, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5185, 'metered']),
  ('partial repair probe: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'AIR', 5437, 250, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5050, 'flat']),
  ('second regression',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'UNI', 'AIR', 1363, 250, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4450, 'flat']),
  ('normal control 1',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'Dt', 'DT', 4478, 600, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [7317, 'metered']),
  ('normal control 2',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'UNI', 5924, 600, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5000, 'flat']),
  ('normal control 3',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'DT', 1853, 250, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5250, 'flat']),
  ('normal control 4',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'Dt', 'MID', 4781, 0, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [7172, 'metered'])],
 [('regression: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'DT', 'air', 1974, 250, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5050, 'flat']),
  ('partial repair probe: airport fee sides',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'MID', 'AIR', 1558, 0, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [2637, 'metered']),
  ('second regression',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'air', 'AIR', 2287, 600, 15,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4831, 'metered']),
  ('normal control 1',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'AIR', 'Dt', 2942, 250, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [5250, 'flat']),
  ('normal control 2',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'AIR', 'SHUT', 3509, 0, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [4009, 'metered']),
  ('normal control 3',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'MID', 'SHUT', 2704, 0, 10,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [2704, 'metered']),
  ('normal control 4',
   [{'AIR|DT': 4500, 'AIR|UNI': 3900, 'DT|SHUT': 0}, 'SHUT', 'DT', 2888, 0, 20,
    {'AIR': {'dropoff': 300, 'pickup': 500}}],
   [0, 'flat'])]]
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)

prompt:
Trips to the airport are charged the higher pickup fee.

Zone names are case-insensitive (normalized upper case). A flat fare table keyed "A|B" applies in both directions; a flat fare (0 is a valid promotional flat) is never surged. Otherwise the metered fare is surged (tenths, half up). Airport fees apply separately: the pickup fee of the pickup zone and the dropoff fee of the dropoff zone. Tolls are added last. Return [fare, flat|metered].

split: open-access


meaning: Fixture-count band, not measured model difficulty

deps: stdlib

prompt:
Requests from exactly ten minutes ago keep inflating demand.

Surge demand counts ride requests [t, rider, zone] in the window (now - window, now]. Each rider counts once, in the zone of their latest request in the window (a later-listed request wins a timestamp tie). Return zone -> count for zones with demand.

split: open-access


prompt:
A rider re-requesting after walking to another zone counts twice.

Surge demand counts ride requests [t, rider, zone] in the window (now - window, now]. Each rider counts once, in the zone of their latest request in the window (a later-listed request wins a timestamp tie). Return zone -> count for zones with demand.

split: open-access


prompt:
Demand stays in the zone the rider left.

Surge demand counts ride requests [t, rider, zone] in the window (now - window, now]. Each rider counts once, in the zone of their latest request in the window (a later-listed request wins a timestamp tie). Return zone -> count for zones with demand.

split: open-access


prompt:
Scheduled or skewed requests stamped in the future raise current demand.

Surge demand counts ride requests [t, rider, zone] in the window (now - window, now]. Each rider counts once, in the zone of their latest request in the window (a later-listed request wins a timestamp tie). Return zone -> count for zones with demand.

split: open-access


source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(pickup_m, pickup_s, policy):
    ex_m = max(0, pickup_m - policy['thr_m']) if pickup_s > policy['thr_s'] else 0
    ex_s = max(0, pickup_s - policy['thr_s'])
    fee = (ex_m * policy['per_km'] * 2 + 1000) // 2000 + -(-ex_s // 60) * policy['per_min']
    return min(fee, policy['cap'])
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: excess distance only',
   [6000, 660, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 153),
  ('partial repair probe: excess distance only',
   [12000, 300, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 600),
  ('second regression', [4801, 900, {'cap': 900, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 1', [4800, 900, {'cap': 900, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 2', [3000, 660, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   30),
  ('normal control 3', [2000, 900, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 4', [3000, 300, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0)],
 [('regression: excess distance only',
   [4801, 400, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 0),
  ('partial repair probe: excess distance only',
   [12000, 300, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 600),
  ('second regression', [6000, 601, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   138),
  ('normal control 1', [3000, 601, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   30),
  ('normal control 2', [4800, 900, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 3', [4800, 900, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 4', [4800, 400, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0)],
 [('regression: excess distance only',
   [12000, 900, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 582),
  ('partial repair probe: excess distance only',
   [12000, 300, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 432),
  ('second regression', [4801, 400, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 1', [3000, 300, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 2', [3000, 660, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   30),
  ('normal control 3', [2000, 601, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   30),
  ('normal control 4', [4800, 660, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   45)],
 [('regression: excess distance only',
   [6000, 900, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 333),
  ('partial repair probe: excess distance only',
   [6000, 300, {'cap': 900, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 72),
  ('second regression', [4801, 300, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 1', [2000, 601, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   30),
  ('normal control 2', [2000, 300, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [2000, 400, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 4', [4800, 601, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   30)],
 [('regression: excess distance only',
   [4801, 601, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 45),
  ('partial repair probe: excess distance only',
   [12000, 600, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 648),
  ('second regression', [12000, 601, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   477),
  ('normal control 1', [2000, 600, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 2', [3000, 300, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [4800, 900, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 4', [2000, 601, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   45)]]
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)

prompt:
A 6 km pickup is charged for all 6 km instead of the 1.2 km beyond the threshold.

A long-pickup fee compensates drivers for pickups beyond thr_m meters and thr_s seconds. The distance part is per_km on meters beyond thr_m (prorated, half up); the time part is per_min on each started minute beyond thr_s; each part uses only its own positive excess. The total is capped at cap cents.

split: open-access


prompt:
A fast long-distance pickup gets a negative time component that offsets the distance fee.

A long-pickup fee compensates drivers for pickups beyond thr_m meters and thr_s seconds. The distance part is per_km on meters beyond thr_m (prorated, half up); the time part is per_min on each started minute beyond thr_s; each part uses only its own positive excess. The total is capped at cap cents.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(pickup_m, pickup_s, policy):
    ex_m = max(0, pickup_m - policy['thr_m'])
    ex_s = max(0, pickup_s - policy['thr_s'])
    fee = (ex_m * policy['per_km'] * 2 + 1000) // 2000 + ex_s // 60 * policy['per_min']
    return min(fee, policy['cap'])
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: time part started minutes',
   [12000, 601, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 462),
  ('partial repair probe: time part started minutes',
   [3000, 660, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 45),
  ('second regression', [12000, 660, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   600),
  ('normal control 1', [4800, 300, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 2', [4801, 600, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [4801, 600, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 4', [3000, 900, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225)],
 [('regression: time part started minutes',
   [3000, 601, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 30),
  ('partial repair probe: time part started minutes',
   [12000, 600, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 432),
  ('second regression', [4800, 660, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   30),
  ('normal control 1', [4801, 900, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 2', [4800, 400, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [6000, 900, {'cap': 900, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   297),
  ('normal control 4', [4800, 300, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0)],
 [('regression: time part started minutes',
   [4800, 601, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 45),
  ('partial repair probe: time part started minutes',
   [4801, 660, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 30),
  ('second regression', [2000, 601, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   30),
  ('normal control 1', [4801, 600, {'cap': 900, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 2', [4801, 600, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [4800, 900, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 4', [12000, 900, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   600)],
 [('regression: time part started minutes',
   [4801, 601, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 45),
  ('partial repair probe: time part started minutes',
   [6000, 660, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 138),
  ('second regression', [6000, 600, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   72),
  ('normal control 1', [2000, 600, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 2', [4800, 600, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [4801, 900, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 4', [2000, 600, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0)],
 [('regression: time part started minutes',
   [4800, 601, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 45),
  ('partial repair probe: time part started minutes',
   [4800, 660, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 30),
  ('second regression', [6000, 600, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   72),
  ('normal control 1', [2000, 900, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   150),
  ('normal control 2', [2000, 300, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [4801, 600, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 4', [4800, 600, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0)]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(pickup_m, pickup_s, policy):
    ex_m = max(0, pickup_m - policy['thr_m'])
    ex_s = max(0, pickup_s - policy['thr_s'])
    fee = (ex_m * policy['per_km'] * 2 + 1000) // 2000 + (ex_s + 59) // 60 * policy['per_min'] if ex_s > 60 else 0
    return min(fee, policy['cap'])
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: time part started minutes',
   [12000, 601, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 462),
  ('partial repair probe: time part started minutes',
   [3000, 660, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 45),
  ('second regression', [12000, 660, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   600),
  ('normal control 1', [4800, 300, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 2', [4801, 600, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [4801, 600, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 4', [3000, 900, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225)],
 [('regression: time part started minutes',
   [3000, 601, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 30),
  ('partial repair probe: time part started minutes',
   [12000, 600, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 432),
  ('second regression', [4800, 660, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   30),
  ('normal control 1', [4801, 900, {'cap': 900, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 2', [4800, 400, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [6000, 900, {'cap': 900, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   297),
  ('normal control 4', [4800, 300, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0)],
 [('regression: time part started minutes',
   [4800, 601, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 45),
  ('partial repair probe: time part started minutes',
   [4801, 660, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 30),
  ('second regression', [2000, 601, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   30),
  ('normal control 1', [4801, 600, {'cap': 900, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 2', [4801, 600, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [4800, 900, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 4', [12000, 900, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   600)],
 [('regression: time part started minutes',
   [4801, 601, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 45),
  ('partial repair probe: time part started minutes',
   [6000, 660, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 138),
  ('second regression', [6000, 600, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   72),
  ('normal control 1', [2000, 600, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 2', [4800, 600, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [4801, 900, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   225),
  ('normal control 4', [2000, 600, {'cap': 600, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0)],
 [('regression: time part started minutes',
   [4800, 601, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}], 45),
  ('partial repair probe: time part started minutes',
   [4800, 660, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}], 30),
  ('second regression', [6000, 600, {'cap': 600, 'per_km': 60, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   72),
  ('normal control 1', [2000, 900, {'cap': 900, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   150),
  ('normal control 2', [2000, 300, {'cap': 900, 'per_km': 60, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 3', [4801, 600, {'cap': 600, 'per_km': 90, 'per_min': 45, 'thr_m': 4800, 'thr_s': 600}],
   0),
  ('normal control 4', [4800, 600, {'cap': 600, 'per_km': 90, 'per_min': 30, 'thr_m': 4800, 'thr_s': 600}],
   0)]]
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)

prompt:
Drivers get nothing for the first 59 seconds beyond the time threshold.

A long-pickup fee compensates drivers for pickups beyond thr_m meters and thr_s seconds. The distance part is per_km on meters beyond thr_m (prorated, half up); the time part is per_min on each started minute beyond thr_s; each part uses only its own positive excess. The total is capped at cap cents.

split: open-access


prompt:
The low end of the range can exceed 90% of the estimate.

Show a fare range from a point estimate in cents: low = 90% of the estimate floored to whole dollars, but never below the minimum fare; high = 110% of the estimate rounded up to whole dollars; if the range is narrower than 2.00 the high end becomes low + 2.00. Return [low, high] cents.

split: open-access


prompt:
Final fares land above the displayed range more often than expected.

Show a fare range from a point estimate in cents: low = 90% of the estimate floored to whole dollars, but never below the minimum fare; high = 110% of the estimate rounded up to whole dollars; if the range is narrower than 2.00 the high end becomes low + 2.00. Return [low, high] cents.

split: open-access


prompt:
Short trips show a 1.00-wide range that the contract forbids.

Show a fare range from a point estimate in cents: low = 90% of the estimate floored to whole dollars, but never below the minimum fare; high = 110% of the estimate rounded up to whole dollars; if the range is narrower than 2.00 the high end becomes low + 2.00. Return [low, high] cents.

split: open-access


prompt:
Short trips show a range whose low end equals the high end.

Show a fare range from a point estimate in cents: low = 90% of the estimate floored to whole dollars, but never below the minimum fare; high = 110% of the estimate rounded up to whole dollars; if the range is narrower than 2.00 the high end becomes low + 2.00. Return [low, high] cents.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(stops, policy):
    if len(stops) >= policy['max_stops']:
        return {'error': 'too_many_stops'}
    waits = [s['wait_s'] for s in stops]
    fee = policy['stop_fee'] * len(stops)
    for w in waits:
        over = w - policy['free_wait']
        if over > 0:
            fee += -(-over // 60) * policy['per_min']
    return {'fee': fee}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: stop limit',
   [[{'wait_s': 300}, {'wait_s': 420}, {'wait_s': 170}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 690}),
  ('partial repair probe: stop limit',
   [[{'wait_s': 240}, {'wait_s': 180}, {'wait_s': 240}, {'wait_s': 181}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'error': 'too_many_stops'}),
  ('second regression',
   [[{'wait_s': 420}, {'wait_s': 60}, {'wait_s': 420}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 770}),
  ('normal control 1', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 0}),
  ('normal control 2',
   [[{'wait_s': 170}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 100}),
  ('normal control 3',
   [[{'wait_s': 300}, {'wait_s': 240}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 290}),
  ('normal control 4', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 0})],
 [('regression: stop limit',
   [[{'wait_s': 0}, {'wait_s': 420}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 500}),
  ('partial repair probe: stop limit',
   [[{'wait_s': 170}, {'wait_s': 300}, {'wait_s': 180}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('second regression',
   [[{'wait_s': 420}, {'wait_s': 181}, {'wait_s': 300}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 730}),
  ('normal control 1',
   [[{'wait_s': 181}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 140}),
  ('normal control 2',
   [[{'wait_s': 181}, {'wait_s': 181}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'fee': 360}),
  ('normal control 3',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 100}),
  ('normal control 4',
   [[{'wait_s': 180}, {'wait_s': 300}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 280})],
 [('regression: stop limit',
   [[{'wait_s': 240}, {'wait_s': 60}, {'wait_s': 420}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 450}),
  ('partial repair probe: stop limit',
   [[{'wait_s': 240}, {'wait_s': 240}, {'wait_s': 170}, {'wait_s': 170}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('second regression',
   [[{'wait_s': 240}, {'wait_s': 181}, {'wait_s': 181}, {'wait_s': 60}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('normal control 1',
   [[{'wait_s': 420}, {'wait_s': 60}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 460}),
  ('normal control 2',
   [[{'wait_s': 60}, {'wait_s': 0}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 300}),
  ('normal control 3',
   [[{'wait_s': 170}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 150}),
  ('normal control 4',
   [[{'wait_s': 420}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 260})],
 [('regression: stop limit',
   [[{'wait_s': 181}, {'wait_s': 170}, {'wait_s': 181}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'fee': 510}),
  ('partial repair probe: stop limit',
   [[{'wait_s': 181}, {'wait_s': 240}, {'wait_s': 180}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'error': 'too_many_stops'}),
  ('second regression',
   [[{'wait_s': 0}, {'wait_s': 60}, {'wait_s': 180}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 450}),
  ('normal control 1',
   [[{'wait_s': 300}, {'wait_s': 170}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 380}),
  ('normal control 2', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 0}),
  ('normal control 3', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 0}),
  ('normal control 4',
   [[{'wait_s': 240}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 190})],
 [('regression: stop limit',
   [[{'wait_s': 300}, {'wait_s': 60}, {'wait_s': 420}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 540}),
  ('partial repair probe: stop limit',
   [[{'wait_s': 240}, {'wait_s': 420}, {'wait_s': 60}, {'wait_s': 0}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'error': 'too_many_stops'}),
  ('second regression',
   [[{'wait_s': 181}, {'wait_s': 170}, {'wait_s': 180}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 330}),
  ('normal control 1',
   [[{'wait_s': 300}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 180}),
  ('normal control 2', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 0}),
  ('normal control 3',
   [[{'wait_s': 240}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 190}),
  ('normal control 4', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 0})]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(stops, policy):
    if len(stops) > policy['max_stops'] + 1:
        return {'error': 'too_many_stops'}
    waits = [s['wait_s'] for s in stops]
    fee = policy['stop_fee'] * len(stops)
    for w in waits:
        over = w - policy['free_wait']
        if over > 0:
            fee += -(-over // 60) * policy['per_min']
    return {'fee': fee}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: stop limit',
   [[{'wait_s': 300}, {'wait_s': 420}, {'wait_s': 170}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 690}),
  ('partial repair probe: stop limit',
   [[{'wait_s': 240}, {'wait_s': 180}, {'wait_s': 240}, {'wait_s': 181}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'error': 'too_many_stops'}),
  ('second regression',
   [[{'wait_s': 420}, {'wait_s': 60}, {'wait_s': 420}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 770}),
  ('normal control 1', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 0}),
  ('normal control 2',
   [[{'wait_s': 170}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 100}),
  ('normal control 3',
   [[{'wait_s': 300}, {'wait_s': 240}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 290}),
  ('normal control 4', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 0})],
 [('regression: stop limit',
   [[{'wait_s': 0}, {'wait_s': 420}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 500}),
  ('partial repair probe: stop limit',
   [[{'wait_s': 170}, {'wait_s': 300}, {'wait_s': 180}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('second regression',
   [[{'wait_s': 420}, {'wait_s': 181}, {'wait_s': 300}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 730}),
  ('normal control 1',
   [[{'wait_s': 181}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 140}),
  ('normal control 2',
   [[{'wait_s': 181}, {'wait_s': 181}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'fee': 360}),
  ('normal control 3',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 100}),
  ('normal control 4',
   [[{'wait_s': 180}, {'wait_s': 300}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 280})],
 [('regression: stop limit',
   [[{'wait_s': 240}, {'wait_s': 60}, {'wait_s': 420}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 450}),
  ('partial repair probe: stop limit',
   [[{'wait_s': 240}, {'wait_s': 240}, {'wait_s': 170}, {'wait_s': 170}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('second regression',
   [[{'wait_s': 240}, {'wait_s': 181}, {'wait_s': 181}, {'wait_s': 60}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('normal control 1',
   [[{'wait_s': 420}, {'wait_s': 60}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 460}),
  ('normal control 2',
   [[{'wait_s': 60}, {'wait_s': 0}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 300}),
  ('normal control 3',
   [[{'wait_s': 170}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 150}),
  ('normal control 4',
   [[{'wait_s': 420}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 260})],
 [('regression: stop limit',
   [[{'wait_s': 181}, {'wait_s': 170}, {'wait_s': 181}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'fee': 510}),
  ('partial repair probe: stop limit',
   [[{'wait_s': 181}, {'wait_s': 240}, {'wait_s': 180}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'error': 'too_many_stops'}),
  ('second regression',
   [[{'wait_s': 0}, {'wait_s': 60}, {'wait_s': 180}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 450}),
  ('normal control 1',
   [[{'wait_s': 300}, {'wait_s': 170}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 380}),
  ('normal control 2', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 0}),
  ('normal control 3', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 0}),
  ('normal control 4',
   [[{'wait_s': 240}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 190})],
 [('regression: stop limit',
   [[{'wait_s': 300}, {'wait_s': 60}, {'wait_s': 420}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 540}),
  ('partial repair probe: stop limit',
   [[{'wait_s': 240}, {'wait_s': 420}, {'wait_s': 60}, {'wait_s': 0}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'error': 'too_many_stops'}),
  ('second regression',
   [[{'wait_s': 181}, {'wait_s': 170}, {'wait_s': 180}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 330}),
  ('normal control 1',
   [[{'wait_s': 300}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 180}),
  ('normal control 2', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 0}),
  ('normal control 3',
   [[{'wait_s': 240}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 190}),
  ('normal control 4', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 0})]]
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)

prompt:
Riders adding the third allowed stop get an error.

Intermediate stops each add stop_fee; up to max_stops stops are allowed, more is an error. Each stop has its own free waiting allowance of free_wait seconds; waiting beyond it at that stop is billed per started minute at per_min. Return the stop fee total in cents.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(stops, policy):
    if len(stops) > policy['max_stops']:
        return {'error': 'too_many_stops'}
    waits = [s['wait_s'] for s in stops]
    fee = policy['stop_fee'] * len(stops)
    for w in [sum(waits)]:
        over = w - policy['free_wait']
        if over > 0:
            fee += -(-over // 60) * policy['per_min']
    return {'fee': fee}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: per-stop free wait',
   [[{'wait_s': 300}, {'wait_s': 180}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 390}),
  ('partial repair probe: per-stop free wait',
   [[{'wait_s': 420}, {'wait_s': 0}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 460}),
  ('second regression',
   [[{'wait_s': 181}, {'wait_s': 300}, {'wait_s': 170}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 390}),
  ('normal control 1', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 0}),
  ('normal control 2', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 0}),
  ('normal control 3',
   [[{'wait_s': 0}, {'wait_s': 181}, {'wait_s': 420}, {'wait_s': 180}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('normal control 4',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 150})],
 [('regression: per-stop free wait',
   [[{'wait_s': 0}, {'wait_s': 300}, {'wait_s': 60}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 380}),
  ('partial repair probe: per-stop free wait',
   [[{'wait_s': 300}, {'wait_s': 60}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 280}),
  ('second regression',
   [[{'wait_s': 300}, {'wait_s': 420}, {'wait_s': 300}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 770}),
  ('normal control 1', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 0}),
  ('normal control 2',
   [[{'wait_s': 181}, {'wait_s': 170}, {'wait_s': 170}, {'wait_s': 300}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'error': 'too_many_stops'}),
  ('normal control 3',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 150}),
  ('normal control 4',
   [[{'wait_s': 170}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 100})],
 [('regression: per-stop free wait',
   [[{'wait_s': 300}, {'wait_s': 240}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 320}),
  ('partial repair probe: per-stop free wait',
   [[{'wait_s': 0}, {'wait_s': 60}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 330}),
  ('second regression',
   [[{'wait_s': 300}, {'wait_s': 240}, {'wait_s': 170}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 390}),
  ('normal control 1', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 0}),
  ('normal control 2',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 100}),
  ('normal control 3',
   [[{'wait_s': 0}, {'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 200}),
  ('normal control 4', [[{'wait_s': 0}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 150})],
 [('regression: per-stop free wait',
   [[{'wait_s': 240}, {'wait_s': 420}, {'wait_s': 420}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 810}),
  ('partial repair probe: per-stop free wait',
   [[{'wait_s': 420}, {'wait_s': 300}, {'wait_s': 60}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 480}),
  ('second regression',
   [[{'wait_s': 240}, {'wait_s': 300}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 320}),
  ('normal control 1',
   [[{'wait_s': 0}, {'wait_s': 180}, {'wait_s': 420}, {'wait_s': 0}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('normal control 2',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 150}),
  ('normal control 3',
   [[{'wait_s': 60}, {'wait_s': 240}, {'wait_s': 181}, {'wait_s': 181}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('normal control 4',
   [[{'wait_s': 420}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 220})],
 [('regression: per-stop free wait',
   [[{'wait_s': 181}, {'wait_s': 300}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 420}),
  ('partial repair probe: per-stop free wait',
   [[{'wait_s': 300}, {'wait_s': 240}, {'wait_s': 60}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'fee': 540}),
  ('second regression',
   [[{'wait_s': 170}, {'wait_s': 300}, {'wait_s': 420}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 540}),
  ('normal control 1', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 0}),
  ('normal control 2',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 150}),
  ('normal control 3',
   [[{'wait_s': 0}, {'wait_s': 170}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 300}),
  ('normal control 4', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 0})]]
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(stops, policy):
    if len(stops) > policy['max_stops']:
        return {'error': 'too_many_stops'}
    waits = [s['wait_s'] for s in stops]
    fee = policy['stop_fee'] * len(stops)
    for w in [sum(waits) - policy['free_wait'] * (len(waits) - 1)]:
        over = w - policy['free_wait']
        if over > 0:
            fee += -(-over // 60) * policy['per_min']
    return {'fee': fee}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: per-stop free wait',
   [[{'wait_s': 300}, {'wait_s': 180}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 390}),
  ('partial repair probe: per-stop free wait',
   [[{'wait_s': 420}, {'wait_s': 0}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 460}),
  ('second regression',
   [[{'wait_s': 181}, {'wait_s': 300}, {'wait_s': 170}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 390}),
  ('normal control 1', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 0}),
  ('normal control 2', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 0}),
  ('normal control 3',
   [[{'wait_s': 0}, {'wait_s': 181}, {'wait_s': 420}, {'wait_s': 180}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('normal control 4',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 150})],
 [('regression: per-stop free wait',
   [[{'wait_s': 0}, {'wait_s': 300}, {'wait_s': 60}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 380}),
  ('partial repair probe: per-stop free wait',
   [[{'wait_s': 300}, {'wait_s': 60}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 280}),
  ('second regression',
   [[{'wait_s': 300}, {'wait_s': 420}, {'wait_s': 300}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 770}),
  ('normal control 1', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 0}),
  ('normal control 2',
   [[{'wait_s': 181}, {'wait_s': 170}, {'wait_s': 170}, {'wait_s': 300}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'error': 'too_many_stops'}),
  ('normal control 3',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 150}),
  ('normal control 4',
   [[{'wait_s': 170}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}], {'fee': 100})],
 [('regression: per-stop free wait',
   [[{'wait_s': 300}, {'wait_s': 240}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 320}),
  ('partial repair probe: per-stop free wait',
   [[{'wait_s': 0}, {'wait_s': 60}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 330}),
  ('second regression',
   [[{'wait_s': 300}, {'wait_s': 240}, {'wait_s': 170}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 390}),
  ('normal control 1', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 0}),
  ('normal control 2',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 100}),
  ('normal control 3',
   [[{'wait_s': 0}, {'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 200}),
  ('normal control 4', [[{'wait_s': 0}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 150})],
 [('regression: per-stop free wait',
   [[{'wait_s': 240}, {'wait_s': 420}, {'wait_s': 420}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 810}),
  ('partial repair probe: per-stop free wait',
   [[{'wait_s': 420}, {'wait_s': 300}, {'wait_s': 60}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 480}),
  ('second regression',
   [[{'wait_s': 240}, {'wait_s': 300}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 320}),
  ('normal control 1',
   [[{'wait_s': 0}, {'wait_s': 180}, {'wait_s': 420}, {'wait_s': 0}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('normal control 2',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 150}),
  ('normal control 3',
   [[{'wait_s': 60}, {'wait_s': 240}, {'wait_s': 181}, {'wait_s': 181}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'error': 'too_many_stops'}),
  ('normal control 4',
   [[{'wait_s': 420}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 220})],
 [('regression: per-stop free wait',
   [[{'wait_s': 181}, {'wait_s': 300}, {'wait_s': 240}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}],
   {'fee': 420}),
  ('partial repair probe: per-stop free wait',
   [[{'wait_s': 300}, {'wait_s': 240}, {'wait_s': 60}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}],
   {'fee': 540}),
  ('second regression',
   [[{'wait_s': 170}, {'wait_s': 300}, {'wait_s': 420}],
    {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 100}],
   {'fee': 540}),
  ('normal control 1', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}], {'fee': 0}),
  ('normal control 2',
   [[{'wait_s': 180}], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 150}], {'fee': 150}),
  ('normal control 3',
   [[{'wait_s': 0}, {'wait_s': 170}], {'free_wait': 180, 'max_stops': 3, 'per_min': 40, 'stop_fee': 150}],
   {'fee': 300}),
  ('normal control 4', [[], {'free_wait': 180, 'max_stops': 3, 'per_min': 30, 'stop_fee': 100}], {'fee': 0})]]
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)

prompt:
Two 2-minute stops are billed although each is within its allowance.

Intermediate stops each add stop_fee; up to max_stops stops are allowed, more is an error. Each stop has its own free waiting allowance of free_wait seconds; waiting beyond it at that stop is billed per started minute at per_min. Return the stop fee total in cents.

split: open-access


broken_source:
"""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 True:
        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: cash-only rounding',
   [4478, 'CHF', 'CHF', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   4478),
  ('partial repair probe: cash-only rounding',
   [1999, 'CHF', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1999),
  ('second regression',
   [1234, 'EUR', 'SEK', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   14154),
  ('normal control 1',
   [1003, 'SEK', 'EUR', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   90),
  ('normal control 2',
   [1999, 'EUR', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1880),
  ('normal control 3',
   [2502, 'EUR', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2350),
  ('normal control 4',
   [1234, 'CHF', 'EUR', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1283)],
 [('regression: cash-only rounding',
   [1999, 'CHF', 'CHF', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1999),
  ('partial repair probe: cash-only rounding',
   [2928, 'CHF', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2928),
  ('second regression',
   [1003, 'EUR', 'CHF', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   943),
  ('normal control 1',
   [1234, 'SEK', 'SEK', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1200),
  ('normal control 2',
   [2502, 'EUR', 'EUR', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2502),
  ('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',
   [517, 'SEK', 'SEK', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   500)],
 [('regression: cash-only rounding',
   [1003, 'EUR', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   943),
  ('partial repair probe: cash-only rounding',
   [1999, 'CHF', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1999),
  ('second regression',
   [1234, 'SEK', 'SEK', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1234),
  ('normal control 1',
   [1796, 'SEK', 'EUR', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   162),
  ('normal control 2',
   [1003, 'SEK', 'EUR', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   90),
  ('normal control 3',
   [2502, 'CHF', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2500),
  ('normal control 4',
   [1234, 'SEK', 'EUR', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   111)],
 [('regression: cash-only rounding',
   [2502, 'SEK', 'SEK', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2502),
  ('partial repair probe: cash-only rounding',
   [1003, 'SEK', 'SEK', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1003),
  ('second regression',
   [2502, 'EUR', 'CHF', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2352),
  ('normal control 1',
   [1234, 'EUR', 'SEK', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   14200),
  ('normal control 2',
   [2502, 'EUR', 'EUR', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2502),
  ('normal control 3',
   [2502, 'EUR', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2350),
  ('normal control 4',
   [4790, 'EUR', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   4505)],
 [('regression: cash-only rounding',
   [1999, 'SEK', 'SEK', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1999),
  ('partial repair probe: cash-only rounding',
   [1999, 'CHF', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1999),
  ('second regression',
   [1234, 'EUR', 'SEK', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   14154),
  ('normal control 1',
   [1999, 'CHF', 'EUR', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2079),
  ('normal control 2',
   [1234, 'EUR', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1160),
  ('normal control 3',
   [1234, 'EUR', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1160),
  ('normal control 4',
   [1003, 'EUR', 'EUR', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1003)]]
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)

source:
"""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 != 'card':
        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: cash-only rounding',
   [4478, 'CHF', 'CHF', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   4478),
  ('partial repair probe: cash-only rounding',
   [1999, 'CHF', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1999),
  ('second regression',
   [1234, 'EUR', 'SEK', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   14154),
  ('normal control 1',
   [1003, 'SEK', 'EUR', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   90),
  ('normal control 2',
   [1999, 'EUR', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1880),
  ('normal control 3',
   [2502, 'EUR', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2350),
  ('normal control 4',
   [1234, 'CHF', 'EUR', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1283)],
 [('regression: cash-only rounding',
   [1999, 'CHF', 'CHF', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1999),
  ('partial repair probe: cash-only rounding',
   [2928, 'CHF', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2928),
  ('second regression',
   [1003, 'EUR', 'CHF', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   943),
  ('normal control 1',
   [1234, 'SEK', 'SEK', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1200),
  ('normal control 2',
   [2502, 'EUR', 'EUR', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2502),
  ('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',
   [517, 'SEK', 'SEK', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   500)],
 [('regression: cash-only rounding',
   [1003, 'EUR', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   943),
  ('partial repair probe: cash-only rounding',
   [1999, 'CHF', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1999),
  ('second regression',
   [1234, 'SEK', 'SEK', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1234),
  ('normal control 1',
   [1796, 'SEK', 'EUR', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   162),
  ('normal control 2',
   [1003, 'SEK', 'EUR', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   90),
  ('normal control 3',
   [2502, 'CHF', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2500),
  ('normal control 4',
   [1234, 'SEK', 'EUR', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   111)],
 [('regression: cash-only rounding',
   [2502, 'SEK', 'SEK', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2502),
  ('partial repair probe: cash-only rounding',
   [1003, 'SEK', 'SEK', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1003),
  ('second regression',
   [2502, 'EUR', 'CHF', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2352),
  ('normal control 1',
   [1234, 'EUR', 'SEK', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   14200),
  ('normal control 2',
   [2502, 'EUR', 'EUR', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2502),
  ('normal control 3',
   [2502, 'EUR', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2350),
  ('normal control 4',
   [4790, 'EUR', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   4505)],
 [('regression: cash-only rounding',
   [1999, 'SEK', 'SEK', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1999),
  ('partial repair probe: cash-only rounding',
   [1999, 'CHF', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1999),
  ('second regression',
   [1234, 'EUR', 'SEK', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   14154),
  ('normal control 1',
   [1999, 'CHF', 'EUR', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   2079),
  ('normal control 2',
   [1234, 'EUR', 'CHF', 'wallet',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1160),
  ('normal control 3',
   [1234, 'EUR', 'CHF', 'cash',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1160),
  ('normal control 4',
   [1003, 'EUR', 'EUR', 'card',
    {'CHFEUR': [104, 100], 'EURCHF': [94, 100], 'EURSEK': [1147, 100], 'SEKEUR': [9, 100]},
    {'CHF': 5, 'SEK': 100}],
   1003)]]
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)

prompt:
Swiss card payments are rounded to 5 centimes.

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.

split: open-access


broken_source:
"""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)

source:
"""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)

prompt:
Francs paid in cash come out at odd centimes after conversion.

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.

split: open-access