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

N = 1
observations = []
def solve(amount, from_cur, to_cur, rates, fee_bp):
    if from_cur == to_cur:
        return [amount, 0]
    value = amount * rates[from_cur]
    fee = value * fee_bp // 10000
    if value > 0 and fee_bp > 0:
        fee = max(fee, 1)
    net = value - fee
    return [net // rates[to_cur], net % rates[to_cur]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('fault site fee rounding #1',
   [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [7, 46]),
  ('regression fee rounding #1',
   [7, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [6, 89]),
  ('regression fee rounding #2',
   [40, 'silver', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 3866]),
  ('regression fee rounding #3',
   [1, 'gem', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [248, 0]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression fee rounding #1',
   [7, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [6, 89]),
  ('fault site fee rounding #1',
   [3, 'gem', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [748, 0]),
  ('regression fee rounding #2',
   [1, 'gem', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [248, 0]),
  ('regression fee rounding #3',
   [1468, 'copper', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [0, 1445]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('fault site fee rounding #1',
   [7, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [17, 41]),
  ('regression fee rounding #1',
   [40, 'silver', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 3866]),
  ('regression fee rounding #2',
   [7, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [17, 23]),
  ('regression fee rounding #3',
   [1, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [2, 48]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('fault site fee rounding #1',
   [3, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [7, 25]),
  ('fault site fee rounding #2',
   [1, 'silver', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [0, 98]),
  ('regression fee rounding #1',
   [2921, 'token', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [292070, 0]),
  ('regression fee rounding #2',
   [2375, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [5936, 90]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [751, 'silver', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [751, 0])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression fee rounding #1',
   [1, 'gem', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [248, 0]),
  ('fault site fee rounding #1',
   [1, 'silver', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [98, 0]),
  ('regression fee rounding #2',
   [40, 'copper', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 38]),
  ('regression fee rounding #3',
   [7, 'silver', 'gem', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [2, 189]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [7, 'gold', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [67669, 0])]]
for label, args, expected in cases[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(amount, from_cur, to_cur, rates, fee_bp):
    if from_cur == to_cur:
        return [amount, 0]
    value = amount * rates[from_cur]
    fee = round(value * fee_bp / 10000)
    if value > 0 and fee_bp > 0:
        fee = max(fee, 1)
    net = value - fee
    return [net // rates[to_cur], net % rates[to_cur]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('fault site fee rounding #1',
   [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [7, 46]),
  ('regression fee rounding #1',
   [7, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [6, 89]),
  ('regression fee rounding #2',
   [40, 'silver', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 3866]),
  ('regression fee rounding #3',
   [1, 'gem', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [248, 0]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression fee rounding #1',
   [7, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [6, 89]),
  ('fault site fee rounding #1',
   [3, 'gem', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [748, 0]),
  ('regression fee rounding #2',
   [1, 'gem', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [248, 0]),
  ('regression fee rounding #3',
   [1468, 'copper', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [0, 1445]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('fault site fee rounding #1',
   [7, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [17, 41]),
  ('regression fee rounding #1',
   [40, 'silver', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 3866]),
  ('regression fee rounding #2',
   [7, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [17, 23]),
  ('regression fee rounding #3',
   [1, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [2, 48]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('fault site fee rounding #1',
   [3, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [7, 25]),
  ('fault site fee rounding #2',
   [1, 'silver', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [0, 98]),
  ('regression fee rounding #1',
   [2921, 'token', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [292070, 0]),
  ('regression fee rounding #2',
   [2375, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [5936, 90]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [751, 'silver', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [751, 0])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression fee rounding #1',
   [1, 'gem', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [248, 0]),
  ('fault site fee rounding #1',
   [1, 'silver', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [98, 0]),
  ('regression fee rounding #2',
   [40, 'copper', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 38]),
  ('regression fee rounding #3',
   [7, 'silver', 'gem', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [2, 189]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [7, 'gold', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [67669, 0])]]
for label, args, expected in cases[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:
Small conversions avoid most of the fee.

rates map currency -> copper value. Same currency returns [amount, 0] without fee. Otherwise value = amount*rate[from]; fee = ceil(value*fee_bp/10000), at least 1 copper when value > 0 and fee_bp > 0 and 0 otherwise; net = value - fee; return [net // rate[to], net % rate[to]] (change in copper).

split: open-access


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

N = 1
observations = []
def solve(amount, from_cur, to_cur, rates, fee_bp):
    if from_cur == to_cur:
        return [amount, 0]
    value = amount * rates[from_cur]
    fee = -(-value * fee_bp // 10000)
    if fee_bp > 0:
        fee = max(fee, 1)
    net = value - fee
    return [net // rates[to_cur], net % rates[to_cur]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('fault site minimum fee gate #1',
   [0, 'gem', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 0]),
  ('fault site minimum fee gate #2',
   [0, 'token', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [0, 0]),
  ('partial repair boundary #1',
   [1, 'gold', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [100, 0]),
  ('partial repair boundary #2',
   [3, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [3, 0]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('fault site minimum fee gate #1',
   [0, 'token', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [0, 0]),
  ('fault site minimum fee gate #2',
   [0, 'silver', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [0, 0]),
  ('partial repair boundary #1',
   [40, 'token', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [40, 0]),
  ('partial repair boundary #2',
   [1, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [100, 0]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('fault site minimum fee gate #1',
   [0, 'copper', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 0]),
  ('fault site minimum fee gate #2',
   [0, 'copper', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [0, 0]),
  ('partial repair boundary #1',
   [40, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [4000, 0]),
  ('partial repair boundary #2',
   [914, 'copper', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [0, 914]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('fault site minimum fee gate #1',
   [0, 'copper', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [0, 0]),
  ('fault site minimum fee gate #2',
   [0, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [0, 0]),
  ('partial repair boundary #1',
   [939, 'token', 'gem', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [375, 150]),
  ('partial repair boundary #2',
   [7, 'copper', 'gem', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [0, 7]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('control #1',
   [751, 'silver', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [751, 0])],
 [('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('fault site minimum fee gate #1',
   [0, 'gold', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [0, 0]),
  ('fault site minimum fee gate #2',
   [0, 'gem', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 0]),
  ('partial repair boundary #1',
   [7, 'gold', 'gem', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [280, 0]),
  ('partial repair boundary #2',
   [2596, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [2596, 0]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('control #1',
   [7, 'gold', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [67669, 0])]]
for label, args, expected in cases[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)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

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

N = 1
observations = []
def solve(amount, from_cur, to_cur, rates, fee_bp):
    if from_cur == to_cur:
        return [amount, 0]
    value = amount * rates[from_cur]
    fee = -(-value * fee_bp // 10000)
    if value > 0:
        fee = max(fee, 1)
    net = value - fee
    return [net // rates[to_cur], net % rates[to_cur]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('fault site minimum fee gate #1',
   [0, 'gem', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 0]),
  ('fault site minimum fee gate #2',
   [0, 'token', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [0, 0]),
  ('partial repair boundary #1',
   [1, 'gold', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [100, 0]),
  ('partial repair boundary #2',
   [3, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [3, 0]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('fault site minimum fee gate #1',
   [0, 'token', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [0, 0]),
  ('fault site minimum fee gate #2',
   [0, 'silver', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [0, 0]),
  ('partial repair boundary #1',
   [40, 'token', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [40, 0]),
  ('partial repair boundary #2',
   [1, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [100, 0]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('fault site minimum fee gate #1',
   [0, 'copper', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 0]),
  ('fault site minimum fee gate #2',
   [0, 'copper', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [0, 0]),
  ('partial repair boundary #1',
   [40, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [4000, 0]),
  ('partial repair boundary #2',
   [914, 'copper', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [0, 914]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('control #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49])],
 [('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('fault site minimum fee gate #1',
   [0, 'copper', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [0, 0]),
  ('fault site minimum fee gate #2',
   [0, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [0, 0]),
  ('partial repair boundary #1',
   [939, 'token', 'gem', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [375, 150]),
  ('partial repair boundary #2',
   [7, 'copper', 'gem', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [0, 7]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('control #1',
   [751, 'silver', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [751, 0])],
 [('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('fault site minimum fee gate #1',
   [0, 'gold', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [0, 0]),
  ('fault site minimum fee gate #2',
   [0, 'gem', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 0]),
  ('partial repair boundary #1',
   [7, 'gold', 'gem', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [280, 0]),
  ('partial repair boundary #2',
   [2596, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 0],
   [2596, 0]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('control #1',
   [7, 'gold', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [67669, 0])]]
for label, args, expected in cases[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:
Exchanging nothing produces a negative balance.

rates map currency -> copper value. Same currency returns [amount, 0] without fee. Otherwise value = amount*rate[from]; fee = ceil(value*fee_bp/10000), at least 1 copper when value > 0 and fee_bp > 0 and 0 otherwise; net = value - fee; return [net // rate[to], net % rate[to]] (change in copper).

split: open-access


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

N = 1
observations = []
def solve(amount, from_cur, to_cur, rates, fee_bp):
    if from_cur == to_cur:
        return [amount, 0]
    value = amount * rates[from_cur]
    fee = -(-value * fee_bp // 10000)
    if value > 0 and fee_bp > 0:
        fee = max(fee, 1)
    net = value - fee
    return [net // rates[to_cur], value % rates[to_cur]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression change remainder #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49]),
  ('regression change remainder #2',
   [1291, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [128777, 25]),
  ('regression change remainder #3',
   [3, 'token', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [2, 99]),
  ('regression change remainder #4',
   [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [7, 46]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [751, 'silver', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [751, 0])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression change remainder #1',
   [1291, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [128777, 25]),
  ('fault site change remainder #1',
   [3, 'copper', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 2]),
  ('regression change remainder #2',
   [3, 'token', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [2, 99]),
  ('regression change remainder #3',
   [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [7, 46]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [751, 'silver', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [751, 0])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('fault site change remainder #1',
   [1, 'copper', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 0]),
  ('regression change remainder #1',
   [3, 'token', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [2, 99]),
  ('regression change remainder #2',
   [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [7, 46]),
  ('regression change remainder #3',
   [7, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [6, 89]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [751, 'silver', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [751, 0])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression change remainder #1',
   [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [7, 46]),
  ('regression change remainder #2',
   [7, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [6, 89]),
  ('regression change remainder #3',
   [40, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [3999, 60]),
  ('regression change remainder #4',
   [7, 'gold', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [698, 25]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [7, 'gold', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [67669, 0])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression change remainder #1',
   [40, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [3999, 60]),
  ('fault site change remainder #1',
   [1, 'token', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [0, 99]),
  ('regression change remainder #2',
   [7, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [17, 41]),
  ('regression change remainder #3',
   [40, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [39, 40]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [1, 'copper', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [1, 0])]]
for label, args, expected in cases[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(amount, from_cur, to_cur, rates, fee_bp):
    if from_cur == to_cur:
        return [amount, 0]
    value = amount * rates[from_cur]
    fee = -(-value * fee_bp // 10000)
    if value > 0 and fee_bp > 0:
        fee = max(fee, 1)
    net = value - fee
    return [net // rates[to_cur], net - net // rates[to_cur]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression change remainder #1',
   [1, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [2, 49]),
  ('regression change remainder #2',
   [1291, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [128777, 25]),
  ('regression change remainder #3',
   [3, 'token', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [2, 99]),
  ('regression change remainder #4',
   [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [7, 46]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [751, 'silver', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [751, 0])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression change remainder #1',
   [1291, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [128777, 25]),
  ('fault site change remainder #1',
   [3, 'copper', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 2]),
  ('regression change remainder #2',
   [3, 'token', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [2, 99]),
  ('regression change remainder #3',
   [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [7, 46]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [751, 'silver', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [751, 0])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('fault site change remainder #1',
   [1, 'copper', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [0, 0]),
  ('regression change remainder #1',
   [3, 'token', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [2, 99]),
  ('regression change remainder #2',
   [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [7, 46]),
  ('regression change remainder #3',
   [7, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [6, 89]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [751, 'silver', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [751, 0])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression change remainder #1',
   [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [7, 46]),
  ('regression change remainder #2',
   [7, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [6, 89]),
  ('regression change remainder #3',
   [40, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [3999, 60]),
  ('regression change remainder #4',
   [7, 'gold', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [698, 25]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [7, 'gold', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 333],
   [67669, 0])],
 [('fee rounds up #1', [3, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 25], [7, 48]),
  ('regression change remainder #1',
   [40, 'gold', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 1],
   [3999, 60]),
  ('fault site change remainder #1',
   [1, 'token', 'silver', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 25],
   [0, 99]),
  ('regression change remainder #2',
   [7, 'gem', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [17, 41]),
  ('regression change remainder #3',
   [40, 'silver', 'token', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 150],
   [39, 40]),
  ('same currency no fee #1',
   [5, 'gold', 'gold', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250}, 150],
   [5, 0]),
  ('zero amount with fee #1', [0, 'gem', 'silver', {'copper': 1, 'silver': 100, 'gem': 250}, 50], [0, 0]),
  ('control #1',
   [1, 'copper', 'copper', {'copper': 1, 'silver': 100, 'gold': 10000, 'gem': 250, 'token': 100}, 50],
   [1, 0])]]
for label, args, expected in cases[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:
Change returned is computed before deducting the fee.

rates map currency -> copper value. Same currency returns [amount, 0] without fee. Otherwise value = amount*rate[from]; fee = ceil(value*fee_bp/10000), at least 1 copper when value > 0 and fee_bp > 0 and 0 otherwise; net = value - fee; return [net // rate[to], net % rate[to]] (change in copper).

split: open-access


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

N = 1
observations = []
def solve(skill, recipe_levels, rolls):
    learn, yellow, green, gray = recipe_levels
    if skill <= learn:
        return {'skill': skill, 'ups': 0, 'error': 'too low'}
    ups = 0
    for r in rolls:
        if skill >= 300:
            break
        if skill < yellow:
            chance = 100
        elif skill < green:
            chance = 75
        elif skill < gray:
            chance = 25
        else:
            chance = 0
        if r < chance:
            skill += 1
            ups += 1
    return {'skill': skill, 'ups': ups}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('fault site learn gate #1', [118, [118, 118, 123, 131], [75, 0, 66, 99, 25]], {'skill': 121, 'ups': 3}),
  ('fault site learn gate #2', [61, [61, 73, 84, 94], [75, 74]], {'skill': 63, 'ups': 2}),
  ('partial repair boundary #1',
   [135, [136, 138, 140, 143], [25, 25, 25, 7, 25, 0, 25, 25]],
   {'skill': 135, 'ups': 0, 'error': 'too low'}),
  ('partial repair boundary #2',
   [79, [80, 91, 104, 106], [16, 74]],
   {'skill': 79, 'ups': 0, 'error': 'too low'}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [23, [8, 14, 23, 38], [75]], {'skill': 23, 'ups': 0})],
 [('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('fault site learn gate #1', [61, [61, 73, 84, 94], [75, 74]], {'skill': 63, 'ups': 2}),
  ('fault site learn gate #2', [203, [203, 209, 219, 219], [13, 14]], {'skill': 205, 'ups': 2}),
  ('partial repair boundary #1',
   [32, [33, 46, 61, 75], [0, 0, 25, 0, 6]],
   {'skill': 32, 'ups': 0, 'error': 'too low'}),
  ('partial repair boundary #2', [75, [76, 79, 94, 104], [75]], {'skill': 75, 'ups': 0, 'error': 'too low'}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [23, [8, 14, 23, 38], [75]], {'skill': 23, 'ups': 0})],
 [('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('fault site learn gate #1',
   [90, [90, 94, 100, 110], [24, 74, 24, 24, 75, 75, 74]],
   {'skill': 95, 'ups': 5}),
  ('fault site learn gate #2',
   [273, [273, 284, 330, 340], [0, 1, 50, 1, 0, 0, 1, 0, 50, 0, 50]],
   {'skill': 284, 'ups': 11}),
  ('partial repair boundary #1',
   [9, [10, 12, 12, 19], [25, 99, 75, 99, 75, 56, 20, 75]],
   {'skill': 9, 'ups': 0, 'error': 'too low'}),
  ('partial repair boundary #2',
   [28, [29, 34, 49, 62], [75, 74, 25, 99, 24, 24, 0, 64]],
   {'skill': 28, 'ups': 0, 'error': 'too low'}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [23, [8, 14, 23, 38], [75]], {'skill': 23, 'ups': 0})],
 [('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('fault site learn gate #1', [64, [64, 79, 92, 99], [25, 75, 24, 74]], {'skill': 68, 'ups': 4}),
  ('fault site learn gate #2',
   [191, [191, 196, 208, 220], [99, 75, 74, 25, 74, 25, 0]],
   {'skill': 198, 'ups': 7}),
  ('partial repair boundary #1',
   [73, [74, 82, 84, 85], [13, 75, 47, 24, 25, 25]],
   {'skill': 73, 'ups': 0, 'error': 'too low'}),
  ('partial repair boundary #2',
   [210, [211, 216, 231, 243], [74, 74, 24]],
   {'skill': 210, 'ups': 0, 'error': 'too low'}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [84, [64, 70, 80, 85], [0, 99, 75, 25, 25, 99, 75, 0]], {'skill': 85, 'ups': 1})],
 [('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('fault site learn gate #1', [218, [218, 220, 224, 239], [74, 99]], {'skill': 220, 'ups': 2}),
  ('fault site learn gate #2', [265, [265, 266, 266, 277], [0, 75, 0, 0, 24]], {'skill': 269, 'ups': 4}),
  ('partial repair boundary #1',
   [65, [66, 71, 77, 79], [24, 24, 0, 24, 99, 25, 74, 0]],
   {'skill': 65, 'ups': 0, 'error': 'too low'}),
  ('partial repair boundary #2',
   [16, [17, 28, 39, 44], [25, 24]],
   {'skill': 16, 'ups': 0, 'error': 'too low'}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [289, [288, 314, 330, 340], [50, 0, 50, 0, 0]], {'skill': 294, 'ups': 5})]]
for label, args, expected in cases[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(skill, recipe_levels, rolls):
    learn, yellow, green, gray = recipe_levels
    if skill + 1 < learn:
        return {'skill': skill, 'ups': 0, 'error': 'too low'}
    ups = 0
    for r in rolls:
        if skill >= 300:
            break
        if skill < yellow:
            chance = 100
        elif skill < green:
            chance = 75
        elif skill < gray:
            chance = 25
        else:
            chance = 0
        if r < chance:
            skill += 1
            ups += 1
    return {'skill': skill, 'ups': ups}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('fault site learn gate #1', [118, [118, 118, 123, 131], [75, 0, 66, 99, 25]], {'skill': 121, 'ups': 3}),
  ('fault site learn gate #2', [61, [61, 73, 84, 94], [75, 74]], {'skill': 63, 'ups': 2}),
  ('partial repair boundary #1',
   [135, [136, 138, 140, 143], [25, 25, 25, 7, 25, 0, 25, 25]],
   {'skill': 135, 'ups': 0, 'error': 'too low'}),
  ('partial repair boundary #2',
   [79, [80, 91, 104, 106], [16, 74]],
   {'skill': 79, 'ups': 0, 'error': 'too low'}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [23, [8, 14, 23, 38], [75]], {'skill': 23, 'ups': 0})],
 [('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('fault site learn gate #1', [61, [61, 73, 84, 94], [75, 74]], {'skill': 63, 'ups': 2}),
  ('fault site learn gate #2', [203, [203, 209, 219, 219], [13, 14]], {'skill': 205, 'ups': 2}),
  ('partial repair boundary #1',
   [32, [33, 46, 61, 75], [0, 0, 25, 0, 6]],
   {'skill': 32, 'ups': 0, 'error': 'too low'}),
  ('partial repair boundary #2', [75, [76, 79, 94, 104], [75]], {'skill': 75, 'ups': 0, 'error': 'too low'}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [23, [8, 14, 23, 38], [75]], {'skill': 23, 'ups': 0})],
 [('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('fault site learn gate #1',
   [90, [90, 94, 100, 110], [24, 74, 24, 24, 75, 75, 74]],
   {'skill': 95, 'ups': 5}),
  ('fault site learn gate #2',
   [273, [273, 284, 330, 340], [0, 1, 50, 1, 0, 0, 1, 0, 50, 0, 50]],
   {'skill': 284, 'ups': 11}),
  ('partial repair boundary #1',
   [9, [10, 12, 12, 19], [25, 99, 75, 99, 75, 56, 20, 75]],
   {'skill': 9, 'ups': 0, 'error': 'too low'}),
  ('partial repair boundary #2',
   [28, [29, 34, 49, 62], [75, 74, 25, 99, 24, 24, 0, 64]],
   {'skill': 28, 'ups': 0, 'error': 'too low'}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [23, [8, 14, 23, 38], [75]], {'skill': 23, 'ups': 0})],
 [('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('fault site learn gate #1', [64, [64, 79, 92, 99], [25, 75, 24, 74]], {'skill': 68, 'ups': 4}),
  ('fault site learn gate #2',
   [191, [191, 196, 208, 220], [99, 75, 74, 25, 74, 25, 0]],
   {'skill': 198, 'ups': 7}),
  ('partial repair boundary #1',
   [73, [74, 82, 84, 85], [13, 75, 47, 24, 25, 25]],
   {'skill': 73, 'ups': 0, 'error': 'too low'}),
  ('partial repair boundary #2',
   [210, [211, 216, 231, 243], [74, 74, 24]],
   {'skill': 210, 'ups': 0, 'error': 'too low'}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [84, [64, 70, 80, 85], [0, 99, 75, 25, 25, 99, 75, 0]], {'skill': 85, 'ups': 1})],
 [('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('fault site learn gate #1', [218, [218, 220, 224, 239], [74, 99]], {'skill': 220, 'ups': 2}),
  ('fault site learn gate #2', [265, [265, 266, 266, 277], [0, 75, 0, 0, 24]], {'skill': 269, 'ups': 4}),
  ('partial repair boundary #1',
   [65, [66, 71, 77, 79], [24, 24, 0, 24, 99, 25, 74, 0]],
   {'skill': 65, 'ups': 0, 'error': 'too low'}),
  ('partial repair boundary #2',
   [16, [17, 28, 39, 44], [25, 24]],
   {'skill': 16, 'ups': 0, 'error': 'too low'}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [289, [288, 314, 330, 340], [50, 0, 50, 0, 0]], {'skill': 294, 'ups': 5})]]
for label, args, expected in cases[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 freshly learned recipe reports skill too low.

recipe_levels = [learn, yellow, green, gray]. Skill below learn cannot craft (error "too low"). Per roll (0..99), while skill < 300: chance 100 below yellow (orange), 75 below green, 25 below gray, else 0; the skill goes up when roll < chance and the color is re-evaluated each craft.

split: open-access


prompt:
Crafting at 300 raises skill to 301.

recipe_levels = [learn, yellow, green, gray]. Skill below learn cannot craft (error "too low"). Per roll (0..99), while skill < 300: chance 100 below yellow (orange), 75 below green, 25 below gray, else 0; the skill goes up when roll < chance and the color is re-evaluated each craft.

split: open-access


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

N = 1
observations = []
def solve(skill, recipe_levels, rolls):
    learn, yellow, green, gray = recipe_levels
    if skill < learn:
        return {'skill': skill, 'ups': 0, 'error': 'too low'}
    ups = 0
    for r in rolls:
        if skill >= 300:
            break
        if skill <= yellow:
            chance = 100
        elif skill < green:
            chance = 75
        elif skill < gray:
            chance = 25
        else:
            chance = 0
        if r < chance:
            skill += 1
            ups += 1
    return {'skill': skill, 'ups': ups}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site orange boundary #1',
   [118, [118, 118, 123, 131], [75, 0, 66, 99, 25]],
   {'skill': 121, 'ups': 3}),
  ('fault site orange boundary #2', [239, [232, 239, 246, 246], [75]], {'skill': 239, 'ups': 0}),
  ('partial repair boundary #1', [60, [55, 61, 68, 78], [99, 0]], {'skill': 62, 'ups': 2}),
  ('partial repair boundary #2', [104, [98, 105, 115, 129], [99, 25, 99, 99]], {'skill': 106, 'ups': 2}),
  ('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [23, [8, 14, 23, 38], [75]], {'skill': 23, 'ups': 0})],
 [('fault site orange boundary #1',
   [90, [90, 94, 100, 110], [24, 74, 24, 24, 75, 75, 74]],
   {'skill': 95, 'ups': 5}),
  ('fault site orange boundary #2', [85, [79, 85, 99, 110], [75, 0, 69, 23]], {'skill': 88, 'ups': 3}),
  ('partial repair boundary #1', [44, [39, 45, 51, 58], [75, 0]], {'skill': 46, 'ups': 2}),
  ('partial repair boundary #2', [218, [218, 220, 224, 239], [74, 99]], {'skill': 220, 'ups': 2}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('control #1', [23, [8, 14, 23, 38], [75]], {'skill': 23, 'ups': 0}),
  ('control #2', [84, [64, 70, 80, 85], [0, 99, 75, 25, 25, 99, 75, 0]], {'skill': 85, 'ups': 1})],
 [('fault site orange boundary #1', [265, [265, 266, 266, 277], [0, 75, 0, 0, 24]], {'skill': 269, 'ups': 4}),
  ('fault site orange boundary #2',
   [228, [227, 234, 240, 240], [0, 99, 75, 0, 75, 7, 75]],
   {'skill': 234, 'ups': 6}),
  ('partial repair boundary #1',
   [122, [122, 128, 142, 150], [24, 74, 0, 75, 99, 99]],
   {'skill': 128, 'ups': 6}),
  ('partial repair boundary #2', [80, [79, 81, 96, 100], [75, 53]], {'skill': 82, 'ups': 2}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [84, [64, 70, 80, 85], [0, 99, 75, 25, 25, 99, 75, 0]], {'skill': 85, 'ups': 1}),
  ('control #2', [289, [288, 314, 330, 340], [50, 0, 50, 0, 0]], {'skill': 294, 'ups': 5})],
 [('fault site orange boundary #1', [182, [167, 182, 188, 193], [76, 0]], {'skill': 183, 'ups': 1}),
  ('fault site orange boundary #2',
   [148, [139, 148, 148, 161], [74, 25, 24, 0, 74, 25, 75, 25]],
   {'skill': 150, 'ups': 2}),
  ('partial repair boundary #1', [181, [180, 182, 184, 187], [99, 16]], {'skill': 183, 'ups': 2}),
  ('partial repair boundary #2', [199, [190, 200, 202, 208], [75, 25, 0, 99]], {'skill': 202, 'ups': 3}),
  ('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('control #1', [142, [114, 127, 141, 154], [0, 25, 0, 52, 99, 0, 24, 75]], {'skill': 146, 'ups': 4}),
  ('control #2', [36, [33, 37, 40, 42], [24, 25, 24]], {'skill': 39, 'ups': 3})],
 [('fault site orange boundary #1',
   [22, [18, 23, 29, 43], [25, 99, 25, 24, 24, 99, 25, 74]],
   {'skill': 28, 'ups': 6}),
  ('fault site orange boundary #2',
   [91, [76, 91, 95, 102], [75, 34, 24, 25, 75, 99, 75]],
   {'skill': 94, 'ups': 3}),
  ('partial repair boundary #1', [21, [8, 22, 25, 32], [75, 25, 74]], {'skill': 24, 'ups': 3}),
  ('partial repair boundary #2', [196, [194, 200, 202, 202], [75, 24, 75, 94]], {'skill': 200, 'ups': 4}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('control #1', [299, [277, 291, 302, 311], [74, 74, 74, 75, 14, 25, 25, 99]], {'skill': 300, 'ups': 1}),
  ('control #2', [100, [90, 100, 102, 105], [25, 25, 75]], {'skill': 102, 'ups': 2})]]
for label, args, expected in cases[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(skill, recipe_levels, rolls):
    learn, yellow, green, gray = recipe_levels
    if skill < learn:
        return {'skill': skill, 'ups': 0, 'error': 'too low'}
    ups = 0
    for r in rolls:
        if skill >= 300:
            break
        if skill < yellow - 1:
            chance = 100
        elif skill < green:
            chance = 75
        elif skill < gray:
            chance = 25
        else:
            chance = 0
        if r < chance:
            skill += 1
            ups += 1
    return {'skill': skill, 'ups': ups}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site orange boundary #1',
   [118, [118, 118, 123, 131], [75, 0, 66, 99, 25]],
   {'skill': 121, 'ups': 3}),
  ('fault site orange boundary #2', [239, [232, 239, 246, 246], [75]], {'skill': 239, 'ups': 0}),
  ('partial repair boundary #1', [60, [55, 61, 68, 78], [99, 0]], {'skill': 62, 'ups': 2}),
  ('partial repair boundary #2', [104, [98, 105, 115, 129], [99, 25, 99, 99]], {'skill': 106, 'ups': 2}),
  ('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [23, [8, 14, 23, 38], [75]], {'skill': 23, 'ups': 0})],
 [('fault site orange boundary #1',
   [90, [90, 94, 100, 110], [24, 74, 24, 24, 75, 75, 74]],
   {'skill': 95, 'ups': 5}),
  ('fault site orange boundary #2', [85, [79, 85, 99, 110], [75, 0, 69, 23]], {'skill': 88, 'ups': 3}),
  ('partial repair boundary #1', [44, [39, 45, 51, 58], [75, 0]], {'skill': 46, 'ups': 2}),
  ('partial repair boundary #2', [218, [218, 220, 224, 239], [74, 99]], {'skill': 220, 'ups': 2}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('control #1', [23, [8, 14, 23, 38], [75]], {'skill': 23, 'ups': 0}),
  ('control #2', [84, [64, 70, 80, 85], [0, 99, 75, 25, 25, 99, 75, 0]], {'skill': 85, 'ups': 1})],
 [('fault site orange boundary #1', [265, [265, 266, 266, 277], [0, 75, 0, 0, 24]], {'skill': 269, 'ups': 4}),
  ('fault site orange boundary #2',
   [228, [227, 234, 240, 240], [0, 99, 75, 0, 75, 7, 75]],
   {'skill': 234, 'ups': 6}),
  ('partial repair boundary #1',
   [122, [122, 128, 142, 150], [24, 74, 0, 75, 99, 99]],
   {'skill': 128, 'ups': 6}),
  ('partial repair boundary #2', [80, [79, 81, 96, 100], [75, 53]], {'skill': 82, 'ups': 2}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('control #1', [84, [64, 70, 80, 85], [0, 99, 75, 25, 25, 99, 75, 0]], {'skill': 85, 'ups': 1}),
  ('control #2', [289, [288, 314, 330, 340], [50, 0, 50, 0, 0]], {'skill': 294, 'ups': 5})],
 [('fault site orange boundary #1', [182, [167, 182, 188, 193], [76, 0]], {'skill': 183, 'ups': 1}),
  ('fault site orange boundary #2',
   [148, [139, 148, 148, 161], [74, 25, 24, 0, 74, 25, 75, 25]],
   {'skill': 150, 'ups': 2}),
  ('partial repair boundary #1', [181, [180, 182, 184, 187], [99, 16]], {'skill': 183, 'ups': 2}),
  ('partial repair boundary #2', [199, [190, 200, 202, 208], [75, 25, 0, 99]], {'skill': 202, 'ups': 3}),
  ('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('at cap #1', [299, [200, 250, 275, 320], [0, 0]], {'skill': 300, 'ups': 1}),
  ('control #1', [142, [114, 127, 141, 154], [0, 25, 0, 52, 99, 0, 24, 75]], {'skill': 146, 'ups': 4}),
  ('control #2', [36, [33, 37, 40, 42], [24, 25, 24]], {'skill': 39, 'ups': 3})],
 [('fault site orange boundary #1',
   [22, [18, 23, 29, 43], [25, 99, 25, 24, 24, 99, 25, 74]],
   {'skill': 28, 'ups': 6}),
  ('fault site orange boundary #2',
   [91, [76, 91, 95, 102], [75, 34, 24, 25, 75, 99, 75]],
   {'skill': 94, 'ups': 3}),
  ('partial repair boundary #1', [21, [8, 22, 25, 32], [75, 25, 74]], {'skill': 24, 'ups': 3}),
  ('partial repair boundary #2', [196, [194, 200, 202, 202], [75, 24, 75, 94]], {'skill': 200, 'ups': 4}),
  ('gray recipe roll zero #1', [90, [50, 60, 70, 80], [0, 0]], {'skill': 90, 'ups': 0}),
  ('exactly at learn level #1', [50, [50, 60, 70, 80], [0]], {'skill': 51, 'ups': 1}),
  ('control #1', [299, [277, 291, 302, 311], [74, 74, 74, 75, 14, 25, 25, 99]], {'skill': 300, 'ups': 1}),
  ('control #2', [100, [90, 100, 102, 105], [25, 25, 75]], {'skill': 102, 'ups': 2})]]
for label, args, expected in cases[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:
Crafting at the yellow threshold still guarantees a skill-up.

recipe_levels = [learn, yellow, green, gray]. Skill below learn cannot craft (error "too low"). Per roll (0..99), while skill < 300: chance 100 below yellow (orange), 75 below green, 25 below gray, else 0; the skill goes up when roll < chance and the color is re-evaluated each craft.

split: open-access


prompt:
Trivial recipes keep leveling the profession.

recipe_levels = [learn, yellow, green, gray]. Skill below learn cannot craft (error "too low"). Per roll (0..99), while skill < 300: chance 100 below yellow (orange), 75 below green, 25 below gray, else 0; the skill goes up when roll < chance and the color is re-evaluated each craft.

split: open-access


prompt:
A zero roll yields a skill-up on gray recipes.

recipe_levels = [learn, yellow, green, gray]. Skill below learn cannot craft (error "too low"). Per roll (0..99), while skill < 300: chance 100 below yellow (orange), 75 below green, 25 below gray, else 0; the skill goes up when roll < chance and the color is re-evaluated each craft.

split: open-access


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

N = 1
observations = []
def solve(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = (sold - target) * 100 // target
        step = price * pct // 100
        if pct > 0:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site rise cap #1', [99, 1188, 396, 6, 782], 118),
  ('fault site rise cap #2', [50, 15, 5, 43, 185], 60),
  ('partial repair boundary #1', [50, 11, 10, 38, 410], 55),
  ('partial repair boundary #2', [99, 42, 40, 39, 750], 103),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47)],
 [('fault site rise cap #1', [99, 267, 89, 48, 886], 118),
  ('fault site rise cap #2', [99, 3, 1, 22, 530], 118),
  ('partial repair boundary #1', [1000, 6, 5, 49, 1369], 1200),
  ('partial repair boundary #2', [99, 11, 10, 44, 1070], 108),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [9, 0, 1, 47, 499], 47),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('fault site rise cap #1', [1000, 75, 40, 44, 1496], 1200),
  ('fault site rise cap #2', [328, 7, 5, 6, 879], 393),
  ('partial repair boundary #1', [50, 11, 10, 1, 1404], 55),
  ('partial repair boundary #2', [99, 6, 5, 12, 1409], 118),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [1000, 0, 0, 7, 47], 47),
  ('control #2', [736, 68, 66, 28, 100], 100)],
 [('fault site rise cap #1', [99, 3, 1, 49, 695], 118),
  ('fault site rise cap #2', [50, 1524, 508, 24, 1269], 60),
  ('partial repair boundary #1', [1000, 11, 10, 18, 1162], 1100),
  ('partial repair boundary #2', [50, 100, 87, 39, 122], 57),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [3, 75, 76, 12, 1170], 12),
  ('control #2', [1000, 5, 5, 37, 1007], 1000)],
 [('fault site rise cap #1', [99, 210, 70, 40, 1422], 118),
  ('fault site rise cap #2', [99, 191, 5, 22, 1290], 118),
  ('partial repair boundary #1', [99, 6, 5, 33, 381], 118),
  ('partial repair boundary #2', [620, 11, 10, 41, 806], 682),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 5, 5, 44, 212], 99),
  ('control #2', [99, -1, 0, 37, 260], 99)]]
for label, args, expected in cases[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(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // sold)
        step = price * pct // 100
        if pct > 0:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site rise cap #1', [99, 1188, 396, 6, 782], 118),
  ('fault site rise cap #2', [50, 15, 5, 43, 185], 60),
  ('partial repair boundary #1', [50, 11, 10, 38, 410], 55),
  ('partial repair boundary #2', [99, 42, 40, 39, 750], 103),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47)],
 [('fault site rise cap #1', [99, 267, 89, 48, 886], 118),
  ('fault site rise cap #2', [99, 3, 1, 22, 530], 118),
  ('partial repair boundary #1', [1000, 6, 5, 49, 1369], 1200),
  ('partial repair boundary #2', [99, 11, 10, 44, 1070], 108),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [9, 0, 1, 47, 499], 47),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('fault site rise cap #1', [1000, 75, 40, 44, 1496], 1200),
  ('fault site rise cap #2', [328, 7, 5, 6, 879], 393),
  ('partial repair boundary #1', [50, 11, 10, 1, 1404], 55),
  ('partial repair boundary #2', [99, 6, 5, 12, 1409], 118),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [1000, 0, 0, 7, 47], 47),
  ('control #2', [736, 68, 66, 28, 100], 100)],
 [('fault site rise cap #1', [99, 3, 1, 49, 695], 118),
  ('fault site rise cap #2', [50, 1524, 508, 24, 1269], 60),
  ('partial repair boundary #1', [1000, 11, 10, 18, 1162], 1100),
  ('partial repair boundary #2', [50, 100, 87, 39, 122], 57),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [3, 75, 76, 12, 1170], 12),
  ('control #2', [1000, 5, 5, 37, 1007], 1000)],
 [('fault site rise cap #1', [99, 210, 70, 40, 1422], 118),
  ('fault site rise cap #2', [99, 191, 5, 22, 1290], 118),
  ('partial repair boundary #1', [99, 6, 5, 33, 381], 118),
  ('partial repair boundary #2', [620, 11, 10, 41, 806], 682),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 5, 5, 44, 212], 99),
  ('control #2', [99, -1, 0, 37, 260], 99)]]
for label, args, expected in cases[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 single sell-out day multiplies the price.

If target <= 0 the price is only clamped to [floor, ceiling]. If sold > target: pct = min(20, floor((sold-target)*100/target)), step = floor(price*pct/100) but at least 1 when pct > 0, new = price + step. If sold < target: pct = min(15, floor((target-sold)*100/target)), new = price - floor(price*pct/100). Otherwise unchanged. Result clamped to [floor, ceiling].

split: open-access


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

N = 1
observations = []
def solve(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if pct > 0:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price * (100 - pct) // 100
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression decrease rounding #1', [50, 42, 70, 38, 107], 43),
  ('regression decrease rounding #2', [99, 39, 40, 15, 1103], 98),
  ('regression decrease rounding #3', [99, 0, 5, 18, 422], 85),
  ('regression decrease rounding #4', [50, 4, 5, 36, 1502], 43),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('regression decrease rounding #1', [99, 0, 5, 18, 422], 85),
  ('regression decrease rounding #2', [50, 4, 5, 36, 1502], 43),
  ('regression decrease rounding #3', [873, 0, 1, 38, 806], 743),
  ('regression decrease rounding #4', [99, 39, 40, 28, 329], 98),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 1188, 396, 6, 782], 118),
  ('control #2', [9, 0, 1, 47, 499], 47)],
 [('regression decrease rounding #1', [873, 0, 1, 38, 806], 743),
  ('fault site decrease rounding #1', [50, 50, 51, 3, 1314], 50),
  ('regression decrease rounding #2', [99, 39, 40, 28, 329], 98),
  ('regression decrease rounding #3', [99, 0, 1, 41, 274], 85),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('regression decrease rounding #1', [99, 39, 40, 28, 329], 98),
  ('fault site decrease rounding #1', [675, 0, 41, 20, 744], 574),
  ('regression decrease rounding #2', [99, 0, 1, 41, 274], 85),
  ('regression decrease rounding #3', [99, 0, 897, 18, 606], 85),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [736, 68, 66, 28, 100], 100),
  ('control #2', [3, 75, 76, 12, 1170], 12)],
 [('regression decrease rounding #1', [99, 0, 1, 41, 274], 85),
  ('regression decrease rounding #2', [99, 0, 897, 18, 606], 85),
  ('regression decrease rounding #3', [99, 4, 5, 14, 1130], 85),
  ('regression decrease rounding #4', [99, 0, 1, 13, 99], 85),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [1000, 5, 5, 37, 1007], 1000),
  ('control #2', [50, 11, 10, 38, 410], 55)]]
for label, args, expected in cases[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(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if pct > 0:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - round(price * pct / 100)
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression decrease rounding #1', [50, 42, 70, 38, 107], 43),
  ('regression decrease rounding #2', [99, 39, 40, 15, 1103], 98),
  ('regression decrease rounding #3', [99, 0, 5, 18, 422], 85),
  ('regression decrease rounding #4', [50, 4, 5, 36, 1502], 43),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('regression decrease rounding #1', [99, 0, 5, 18, 422], 85),
  ('regression decrease rounding #2', [50, 4, 5, 36, 1502], 43),
  ('regression decrease rounding #3', [873, 0, 1, 38, 806], 743),
  ('regression decrease rounding #4', [99, 39, 40, 28, 329], 98),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 1188, 396, 6, 782], 118),
  ('control #2', [9, 0, 1, 47, 499], 47)],
 [('regression decrease rounding #1', [873, 0, 1, 38, 806], 743),
  ('fault site decrease rounding #1', [50, 50, 51, 3, 1314], 50),
  ('regression decrease rounding #2', [99, 39, 40, 28, 329], 98),
  ('regression decrease rounding #3', [99, 0, 1, 41, 274], 85),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('regression decrease rounding #1', [99, 39, 40, 28, 329], 98),
  ('fault site decrease rounding #1', [675, 0, 41, 20, 744], 574),
  ('regression decrease rounding #2', [99, 0, 1, 41, 274], 85),
  ('regression decrease rounding #3', [99, 0, 897, 18, 606], 85),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [736, 68, 66, 28, 100], 100),
  ('control #2', [3, 75, 76, 12, 1170], 12)],
 [('regression decrease rounding #1', [99, 0, 1, 41, 274], 85),
  ('regression decrease rounding #2', [99, 0, 897, 18, 606], 85),
  ('regression decrease rounding #3', [99, 4, 5, 14, 1130], 85),
  ('regression decrease rounding #4', [99, 0, 1, 13, 99], 85),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [1000, 5, 5, 37, 1007], 1000),
  ('control #2', [50, 11, 10, 38, 410], 55)]]
for label, args, expected in cases[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:
Prices fall one coin more than the floor rule.

If target <= 0 the price is only clamped to [floor, ceiling]. If sold > target: pct = min(20, floor((sold-target)*100/target)), step = floor(price*pct/100) but at least 1 when pct > 0, new = price + step. If sold < target: pct = min(15, floor((target-sold)*100/target)), new = price - floor(price*pct/100). Otherwise unchanged. Result clamped to [floor, ceiling].

split: open-access


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

N = 1
observations = []
def solve(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if pct > 1:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site minimum rise step #1', [99, 904, 890, 36, 258], 100),
  ('fault site minimum rise step #2', [50, 76, 75, 35, 345], 51),
  ('partial repair boundary #1', [50, 253, 252, 38, 195], 50),
  ('partial repair boundary #2', [50, 734, 732, 21, 710], 50),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('fault site minimum rise step #1', [9, 898, 884, 8, 34], 10),
  ('fault site minimum rise step #2', [99, 806, 793, 1, 532], 100),
  ('partial repair boundary #1', [99, 623, 621, 46, 1542], 99),
  ('partial repair boundary #2', [50, 253, 252, 38, 195], 50),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 1188, 396, 6, 782], 118),
  ('control #2', [9, 0, 1, 47, 499], 47)],
 [('fault site minimum rise step #1', [50, 830, 817, 5, 563], 51),
  ('fault site minimum rise step #2', [50, 80, 79, 32, 704], 51),
  ('partial repair boundary #1', [50, 734, 732, 21, 710], 50),
  ('partial repair boundary #2', [99, 623, 621, 46, 1542], 99),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('fault site minimum rise step #1', [99, 924, 909, 17, 254], 100),
  ('fault site minimum rise step #2', [99, 904, 890, 36, 258], 100),
  ('partial repair boundary #1', [50, 253, 252, 38, 195], 50),
  ('partial repair boundary #2', [50, 734, 732, 21, 710], 50),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [736, 68, 66, 28, 100], 100),
  ('control #2', [3, 75, 76, 12, 1170], 12)],
 [('fault site minimum rise step #1', [50, 76, 75, 35, 345], 51),
  ('fault site minimum rise step #2', [9, 898, 884, 8, 34], 10),
  ('partial repair boundary #1', [99, 623, 621, 46, 1542], 99),
  ('partial repair boundary #2', [50, 253, 252, 38, 195], 50),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [1000, 5, 5, 37, 1007], 1000),
  ('control #2', [50, 11, 10, 38, 410], 55)]]
for label, args, expected in cases[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(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if step == 0:
            step = 1
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site minimum rise step #1', [99, 904, 890, 36, 258], 100),
  ('fault site minimum rise step #2', [50, 76, 75, 35, 345], 51),
  ('partial repair boundary #1', [50, 253, 252, 38, 195], 50),
  ('partial repair boundary #2', [50, 734, 732, 21, 710], 50),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('fault site minimum rise step #1', [9, 898, 884, 8, 34], 10),
  ('fault site minimum rise step #2', [99, 806, 793, 1, 532], 100),
  ('partial repair boundary #1', [99, 623, 621, 46, 1542], 99),
  ('partial repair boundary #2', [50, 253, 252, 38, 195], 50),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 1188, 396, 6, 782], 118),
  ('control #2', [9, 0, 1, 47, 499], 47)],
 [('fault site minimum rise step #1', [50, 830, 817, 5, 563], 51),
  ('fault site minimum rise step #2', [50, 80, 79, 32, 704], 51),
  ('partial repair boundary #1', [50, 734, 732, 21, 710], 50),
  ('partial repair boundary #2', [99, 623, 621, 46, 1542], 99),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('fault site minimum rise step #1', [99, 924, 909, 17, 254], 100),
  ('fault site minimum rise step #2', [99, 904, 890, 36, 258], 100),
  ('partial repair boundary #1', [50, 253, 252, 38, 195], 50),
  ('partial repair boundary #2', [50, 734, 732, 21, 710], 50),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [736, 68, 66, 28, 100], 100),
  ('control #2', [3, 75, 76, 12, 1170], 12)],
 [('fault site minimum rise step #1', [50, 76, 75, 35, 345], 51),
  ('fault site minimum rise step #2', [9, 898, 884, 8, 34], 10),
  ('partial repair boundary #1', [99, 623, 621, 46, 1542], 99),
  ('partial repair boundary #2', [50, 253, 252, 38, 195], 50),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [1000, 5, 5, 37, 1007], 1000),
  ('control #2', [50, 11, 10, 38, 410], 55)]]
for label, args, expected in cases[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:
Low-priced items stay flat despite a 1% overshoot.

If target <= 0 the price is only clamped to [floor, ceiling]. If sold > target: pct = min(20, floor((sold-target)*100/target)), step = floor(price*pct/100) but at least 1 when pct > 0, new = price + step. If sold < target: pct = min(15, floor((target-sold)*100/target)), new = price - floor(price*pct/100). Otherwise unchanged. Result clamped to [floor, ceiling].

split: open-access


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

N = 1
observations = []
def solve(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if pct > 0:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return max(new, floor)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site band clamp #1', [736, 68, 66, 28, 100], 100),
  ('fault site band clamp #2', [1833, 42, 40, 20, 549], 549),
  ('partial repair boundary #1', [9, 0, 1, 47, 499], 47),
  ('partial repair boundary #2', [3, 75, 76, 12, 1170], 12),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('fault site band clamp #1', [1449, 42, 40, 8, 680], 680),
  ('fault site band clamp #2', [508, 144, 365, 8, 95], 95),
  ('partial repair boundary #1', [3, 0, 10, 26, 481], 26),
  ('partial repair boundary #2', [1, 0, 40, 29, 801], 29),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 1188, 396, 6, 782], 118),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('fault site band clamp #1', [50, 16, 1, 43, 49], 49),
  ('fault site band clamp #2', [1000, 30, 10, 17, 816], 816),
  ('partial repair boundary #1', [1, 672, 671, 16, 40], 16),
  ('partial repair boundary #2', [9, 581, 582, 29, 801], 29),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [1000, 0, 0, 7, 47], 47),
  ('control #2', [1000, 5, 5, 37, 1007], 1000)],
 [('fault site band clamp #1', [1369, 46, 45, 46, 340], 340),
  ('fault site band clamp #2', [1314, 55, 55, 10, 1281], 1281),
  ('partial repair boundary #1', [50, 0, 1, 48, 402], 48),
  ('partial repair boundary #2', [1, 85, 84, 28, 1011], 28),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [50, 11, 10, 38, 410], 55),
  ('control #2', [99, 5, 5, 44, 212], 99)],
 [('fault site band clamp #1', [1167, 2, 1, 43, 172], 172),
  ('fault site band clamp #2', [1000, 96, 95, 44, 489], 489),
  ('partial repair boundary #1', [3, 40, 40, 47, 590], 47),
  ('partial repair boundary #2', [9, 53, 53, 21, 719], 21),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, -1, 0, 37, 260], 99),
  ('control #2', [50, 42, 70, 38, 107], 43)]]
for label, args, expected in cases[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(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(max(price, floor), ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if pct > 0:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return min(new, ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('fault site band clamp #1', [736, 68, 66, 28, 100], 100),
  ('fault site band clamp #2', [1833, 42, 40, 20, 549], 549),
  ('partial repair boundary #1', [9, 0, 1, 47, 499], 47),
  ('partial repair boundary #2', [3, 75, 76, 12, 1170], 12),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('fault site band clamp #1', [1449, 42, 40, 8, 680], 680),
  ('fault site band clamp #2', [508, 144, 365, 8, 95], 95),
  ('partial repair boundary #1', [3, 0, 10, 26, 481], 26),
  ('partial repair boundary #2', [1, 0, 40, 29, 801], 29),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, 1188, 396, 6, 782], 118),
  ('control #2', [1000, 0, 0, 7, 47], 47)],
 [('fault site band clamp #1', [50, 16, 1, 43, 49], 49),
  ('fault site band clamp #2', [1000, 30, 10, 17, 816], 816),
  ('partial repair boundary #1', [1, 672, 671, 16, 40], 16),
  ('partial repair boundary #2', [9, 581, 582, 29, 801], 29),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [1000, 0, 0, 7, 47], 47),
  ('control #2', [1000, 5, 5, 37, 1007], 1000)],
 [('fault site band clamp #1', [1369, 46, 45, 46, 340], 340),
  ('fault site band clamp #2', [1314, 55, 55, 10, 1281], 1281),
  ('partial repair boundary #1', [50, 0, 1, 48, 402], 48),
  ('partial repair boundary #2', [1, 85, 84, 28, 1011], 28),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('control #1', [50, 11, 10, 38, 410], 55),
  ('control #2', [99, 5, 5, 44, 212], 99)],
 [('fault site band clamp #1', [1167, 2, 1, 43, 172], 172),
  ('fault site band clamp #2', [1000, 96, 95, 44, 489], 489),
  ('partial repair boundary #1', [3, 40, 40, 47, 590], 47),
  ('partial repair boundary #2', [9, 53, 53, 21, 719], 21),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('control #1', [99, -1, 0, 37, 260], 99),
  ('control #2', [50, 42, 70, 38, 107], 43)]]
for label, args, expected in cases[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:
Popular items climb past the configured ceiling.

If target <= 0 the price is only clamped to [floor, ceiling]. If sold > target: pct = min(20, floor((sold-target)*100/target)), step = floor(price*pct/100) but at least 1 when pct > 0, new = price + step. If sold < target: pct = min(15, floor((target-sold)*100/target)), new = price - floor(price*pct/100). Otherwise unchanged. Result clamped to [floor, ceiling].

split: open-access


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

N = 1
observations = []
def solve(price, sold, target, floor, ceiling):
    if target <= 0:
        return price
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if pct > 0:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('fault site untargeted clamp #1', [1000, 0, 0, 7, 47], 47),
  ('fault site untargeted clamp #2', [1000, 0, 0, 22, 503], 503),
  ('regression untargeted clamp #1', [1, 71, 0, 40, 55], 40),
  ('regression untargeted clamp #2', [9, 1, 0, 18, 1291], 18),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('fault site untargeted clamp #1', [1000, 0, 0, 22, 503], 503),
  ('fault site untargeted clamp #2', [1817, 170, 0, 27, 1161], 1161),
  ('regression untargeted clamp #1', [9, 1, 0, 18, 1291], 18),
  ('regression untargeted clamp #2', [3, 0, 0, 46, 987], 46),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('regression untargeted clamp #1', [1, 71, 0, 40, 55], 40),
  ('regression untargeted clamp #2', [9, 1, 0, 18, 1291], 18),
  ('regression untargeted clamp #3', [1, 0, 0, 31, 1106], 31),
  ('regression untargeted clamp #4', [1, 2, 0, 50, 1234], 50),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('fault site untargeted clamp #1', [1000, 109, 0, 3, 331], 331),
  ('regression untargeted clamp #1', [3, 0, 0, 46, 987], 46),
  ('regression untargeted clamp #2', [1, 2, 0, 47, 1435], 47),
  ('regression untargeted clamp #3', [9, 0, 0, 22, 719], 22),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47)],
 [('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('regression untargeted clamp #1', [1, 0, 0, 31, 1106], 31),
  ('fault site untargeted clamp #1', [1000, 0, 0, 15, 739], 739),
  ('regression untargeted clamp #2', [1, 0, 0, 4, 964], 4),
  ('regression untargeted clamp #3', [1, 0, 0, 16, 930], 16),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [736, 68, 66, 28, 100], 100)]]
for label, args, expected in cases[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(price, sold, target, floor, ceiling):
    if target <= 0:
        return min(price, ceiling)
    if sold > target:
        pct = min(20, (sold - target) * 100 // target)
        step = price * pct // 100
        if pct > 0:
            step = max(step, 1)
        new = price + step
    elif sold < target:
        pct = min(15, (target - sold) * 100 // target)
        new = price - price * pct // 100
    else:
        new = price
    return min(max(new, floor), ceiling)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('fault site untargeted clamp #1', [1000, 0, 0, 7, 47], 47),
  ('fault site untargeted clamp #2', [1000, 0, 0, 22, 503], 503),
  ('regression untargeted clamp #1', [1, 71, 0, 40, 55], 40),
  ('regression untargeted clamp #2', [9, 1, 0, 18, 1291], 18),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('fault site untargeted clamp #1', [1000, 0, 0, 22, 503], 503),
  ('fault site untargeted clamp #2', [1817, 170, 0, 27, 1161], 1161),
  ('regression untargeted clamp #1', [9, 1, 0, 18, 1291], 18),
  ('regression untargeted clamp #2', [3, 0, 0, 46, 987], 46),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('regression untargeted clamp #1', [1, 71, 0, 40, 55], 40),
  ('regression untargeted clamp #2', [9, 1, 0, 18, 1291], 18),
  ('regression untargeted clamp #3', [1, 0, 0, 31, 1106], 31),
  ('regression untargeted clamp #4', [1, 2, 0, 50, 1234], 50),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [99, 1188, 396, 6, 782], 118)],
 [('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('fault site untargeted clamp #1', [1000, 109, 0, 3, 331], 331),
  ('regression untargeted clamp #1', [3, 0, 0, 46, 987], 46),
  ('regression untargeted clamp #2', [1, 2, 0, 47, 1435], 47),
  ('regression untargeted clamp #3', [9, 0, 0, 22, 719], 22),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [9, 0, 1, 47, 499], 47)],
 [('no target listed #1', [5, 3, 0, 10, 50], 10),
  ('regression untargeted clamp #1', [1, 0, 0, 31, 1106], 31),
  ('fault site untargeted clamp #1', [1000, 0, 0, 15, 739], 739),
  ('regression untargeted clamp #2', [1, 0, 0, 4, 964], 4),
  ('regression untargeted clamp #3', [1, 0, 0, 16, 930], 16),
  ('cheap item rises one #1', [3, 13, 10, 1, 100], 4),
  ('crash capped at 15 #1', [1000, 0, 40, 1, 5000], 850),
  ('control #1', [736, 68, 66, 28, 100], 100)]]
for label, args, expected in cases[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:
Items without a sales target keep out-of-band prices.

If target <= 0 the price is only clamped to [floor, ceiling]. If sold > target: pct = min(20, floor((sold-target)*100/target)), step = floor(price*pct/100) but at least 1 when pct > 0, new = price + step. If sold < target: pct = min(15, floor((target-sold)*100/target)), new = price - floor(price*pct/100). Otherwise unchanged. Result clamped to [floor, ceiling].

split: open-access