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

N = 1
observations = []
def solve(x):
    rate = x['initial_bp']
    out = []
    life_max = x['initial_bp'] + x['lifetime_cap_bp']
    for i, idx in enumerate(x['index_path']):
        fi = idx + x['margin_bp']
        q, r = divmod(fi, x['round_to'])
        fi = (q + (1 if 2 * r >= x['round_to'] else 0)) * x['round_to']
        cap = x['initial_cap_bp'] if i == 0 else x['periodic_cap_bp']
        new = min(fi, rate + cap)
        new = max(x['floor_bp'], min(new, life_max))
        out.append(new)
        rate = new
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: downward adjustment cap', {'initial_bp': 450, 'index_path': [250, 650, 100, 650, 650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 675]], ['regression: downward adjustment cap, partial-repair probe', {'initial_bp': 450, 'index_path': [50, 700], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [250, 350]], ['control 1', {'initial_bp': 500, 'index_path': [212, 100, 50, 250, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 400, 400, 500, 600]], ['control 2', {'initial_bp': 500, 'index_path': [650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [875]], ['control 3', {'initial_bp': 450, 'index_path': [50, 537, 400, 650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [375, 475, 575, 675]], ['control 4', {'initial_bp': 300, 'index_path': [212, 212], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [475, 475]], ['control 5', {'initial_bp': 300, 'index_path': [100, 50, 250], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [400, 350, 550]]], [['regression: downward adjustment cap', {'initial_bp': 450, 'index_path': [650, 50, 212], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [650, 550, 500]], ['regression: downward adjustment cap, partial-repair probe', {'initial_bp': 500, 'index_path': [212], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [375]], ['control 1', {'initial_bp': 450, 'index_path': [250, 100, 700], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 325, 525]], ['control 2', {'initial_bp': 450, 'index_path': [400, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [625, 825]], ['control 3', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [525]], ['control 4', {'initial_bp': 450, 'index_path': [50], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [400]], ['control 5', {'initial_bp': 500, 'index_path': [212], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500]]], [['regression: downward adjustment cap', {'initial_bp': 450, 'index_path': [212, 650, 50, 650], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [500, 700, 500, 700]], ['regression: downward adjustment cap, partial-repair probe', {'initial_bp': 500, 'index_path': [50, 50, 50], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [350, 350, 350]], ['control 1', {'initial_bp': 450, 'index_path': [250, 250, 212], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 450]], ['control 2', {'initial_bp': 450, 'index_path': [100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400]], ['control 3', {'initial_bp': 500, 'index_path': [212, 537], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 700]], ['control 4', {'initial_bp': 500, 'index_path': [700], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [1000]], ['control 5', {'initial_bp': 300, 'index_path': [650, 650], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [800, 900]]], [['regression: downward adjustment cap', {'initial_bp': 450, 'index_path': [537, 250, 212, 212], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [650, 550, 450, 450]], ['regression: downward adjustment cap, partial-repair probe', {'initial_bp': 450, 'index_path': [50], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [250]], ['control 1', {'initial_bp': 300, 'index_path': [650, 250, 50, 537, 50], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 375, 575, 375]], ['control 2', {'initial_bp': 300, 'index_path': [400, 400, 537], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 675, 800]], ['control 3', {'initial_bp': 500, 'index_path': [537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [700]], ['control 4', {'initial_bp': 300, 'index_path': [250, 250, 250], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500, 500, 500]], ['control 5', {'initial_bp': 500, 'index_path': [100, 212, 100], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [350, 450, 350]]], [['regression: downward adjustment cap', {'initial_bp': 300, 'index_path': [400, 537, 100], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 700, 500]], ['regression: downward adjustment cap, partial-repair probe', {'initial_bp': 450, 'index_path': [50, 650, 700, 400], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [250, 350, 450, 550]], ['control 1', {'initial_bp': 450, 'index_path': [650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875]], ['control 2', {'initial_bp': 300, 'index_path': [50, 650, 50, 250, 537], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400, 600, 400, 500, 700]], ['control 3', {'initial_bp': 450, 'index_path': [400, 537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [650, 775]], ['control 4', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500]], ['control 5', {'initial_bp': 450, 'index_path': [250, 537, 250, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 600, 500, 600]]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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(x):
    rate = x['initial_bp']
    out = []
    life_max = x['initial_bp'] + x['lifetime_cap_bp']
    for i, idx in enumerate(x['index_path']):
        fi = idx + x['margin_bp']
        q, r = divmod(fi, x['round_to'])
        fi = (q + (1 if 2 * r >= x['round_to'] else 0)) * x['round_to']
        cap = x['initial_cap_bp'] if i == 0 else x['periodic_cap_bp']
        new = max(rate - x['periodic_cap_bp'], min(fi, rate + cap))
        new = max(x['floor_bp'], min(new, life_max))
        out.append(new)
        rate = new
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: downward adjustment cap', {'initial_bp': 450, 'index_path': [250, 650, 100, 650, 650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 675]], ['regression: downward adjustment cap, partial-repair probe', {'initial_bp': 450, 'index_path': [50, 700], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [250, 350]], ['control 1', {'initial_bp': 500, 'index_path': [212, 100, 50, 250, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 400, 400, 500, 600]], ['control 2', {'initial_bp': 500, 'index_path': [650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [875]], ['control 3', {'initial_bp': 450, 'index_path': [50, 537, 400, 650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [375, 475, 575, 675]], ['control 4', {'initial_bp': 300, 'index_path': [212, 212], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [475, 475]], ['control 5', {'initial_bp': 300, 'index_path': [100, 50, 250], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [400, 350, 550]]], [['regression: downward adjustment cap', {'initial_bp': 450, 'index_path': [650, 50, 212], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [650, 550, 500]], ['regression: downward adjustment cap, partial-repair probe', {'initial_bp': 500, 'index_path': [212], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [375]], ['control 1', {'initial_bp': 450, 'index_path': [250, 100, 700], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 325, 525]], ['control 2', {'initial_bp': 450, 'index_path': [400, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [625, 825]], ['control 3', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [525]], ['control 4', {'initial_bp': 450, 'index_path': [50], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [400]], ['control 5', {'initial_bp': 500, 'index_path': [212], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500]]], [['regression: downward adjustment cap', {'initial_bp': 450, 'index_path': [212, 650, 50, 650], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [500, 700, 500, 700]], ['regression: downward adjustment cap, partial-repair probe', {'initial_bp': 500, 'index_path': [50, 50, 50], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [350, 350, 350]], ['control 1', {'initial_bp': 450, 'index_path': [250, 250, 212], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 450]], ['control 2', {'initial_bp': 450, 'index_path': [100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400]], ['control 3', {'initial_bp': 500, 'index_path': [212, 537], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 700]], ['control 4', {'initial_bp': 500, 'index_path': [700], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [1000]], ['control 5', {'initial_bp': 300, 'index_path': [650, 650], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [800, 900]]], [['regression: downward adjustment cap', {'initial_bp': 450, 'index_path': [537, 250, 212, 212], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [650, 550, 450, 450]], ['regression: downward adjustment cap, partial-repair probe', {'initial_bp': 450, 'index_path': [50], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [250]], ['control 1', {'initial_bp': 300, 'index_path': [650, 250, 50, 537, 50], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 375, 575, 375]], ['control 2', {'initial_bp': 300, 'index_path': [400, 400, 537], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 675, 800]], ['control 3', {'initial_bp': 500, 'index_path': [537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [700]], ['control 4', {'initial_bp': 300, 'index_path': [250, 250, 250], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500, 500, 500]], ['control 5', {'initial_bp': 500, 'index_path': [100, 212, 100], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [350, 450, 350]]], [['regression: downward adjustment cap', {'initial_bp': 300, 'index_path': [400, 537, 100], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 700, 500]], ['regression: downward adjustment cap, partial-repair probe', {'initial_bp': 450, 'index_path': [50, 650, 700, 400], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [250, 350, 450, 550]], ['control 1', {'initial_bp': 450, 'index_path': [650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875]], ['control 2', {'initial_bp': 300, 'index_path': [50, 650, 50, 250, 537], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400, 600, 400, 500, 700]], ['control 3', {'initial_bp': 450, 'index_path': [400, 537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [650, 775]], ['control 4', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500]], ['control 5', {'initial_bp': 450, 'index_path': [250, 537, 250, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 600, 500, 600]]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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:
The note rate drops by more than the cap when the index falls.

x = {'initial_bp', 'index_path': index at each reset, 'margin_bp', 'round_to', 'initial_cap_bp', 'periodic_cap_bp', 'lifetime_cap_bp' (above initial), 'floor_bp'}. At each reset the fully indexed rate index + margin is rounded half-up to a multiple of round_to, limited to within the cap of the previous note rate (initial cap at the first reset, periodic afterwards, both directions), then limited to [floor_bp, initial + lifetime cap]. Return the list of note rates.

split: open-access


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

N = 1
observations = []
def solve(x):
    rate = x['initial_bp']
    out = []
    life_max = x['initial_bp'] + x['lifetime_cap_bp']
    for i, idx in enumerate(x['index_path']):
        fi = idx + x['margin_bp']
        q, r = divmod(fi, x['round_to'])
        fi = (q + (1 if r else 0)) * x['round_to']
        cap = x['initial_cap_bp'] if i == 0 else x['periodic_cap_bp']
        new = max(rate - cap, min(fi, rate + cap))
        new = max(x['floor_bp'], min(new, life_max))
        out.append(new)
        rate = new
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: rate increment rounding', {'initial_bp': 500, 'index_path': [700, 50, 700, 50, 100], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875, 675, 875, 675, 475]], ['regression: rate increment rounding, partial-repair probe', {'initial_bp': 300, 'index_path': [100, 50, 250], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [400, 350, 550]], ['control 1', {'initial_bp': 500, 'index_path': [212, 100, 50, 250, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 400, 400, 500, 600]], ['control 2', {'initial_bp': 450, 'index_path': [250, 650, 100, 650, 650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 675]], ['control 3', {'initial_bp': 500, 'index_path': [650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [875]], ['control 4', {'initial_bp': 450, 'index_path': [50, 537, 400, 650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [375, 475, 575, 675]], ['control 5', {'initial_bp': 300, 'index_path': [650, 212, 100], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 500, 400]]], [['regression: rate increment rounding', {'initial_bp': 500, 'index_path': [537, 650, 250, 400, 537], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [700, 875, 675, 625, 750]], ['regression: rate increment rounding, partial-repair probe', {'initial_bp': 500, 'index_path': [50], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [350]], ['control 1', {'initial_bp': 450, 'index_path': [650, 50, 212], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [650, 550, 500]], ['control 2', {'initial_bp': 300, 'index_path': [650, 50, 700], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [800, 600, 800]], ['control 3', {'initial_bp': 450, 'index_path': [250, 100, 700], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 325, 525]], ['control 4', {'initial_bp': 500, 'index_path': [250, 400, 50, 700, 400], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 625]], ['control 5', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [525]]], [['regression: rate increment rounding', {'initial_bp': 300, 'index_path': [537, 700, 250], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [750, 850, 750]], ['regression: rate increment rounding, partial-repair probe', {'initial_bp': 450, 'index_path': [250, 250, 212], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 450]], ['control 1', {'initial_bp': 450, 'index_path': [212, 650, 50, 650], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [500, 700, 500, 700]], ['control 2', {'initial_bp': 450, 'index_path': [537, 50, 537], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [650, 550, 650]], ['control 3', {'initial_bp': 450, 'index_path': [100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400]], ['control 4', {'initial_bp': 500, 'index_path': [700, 250], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [1000, 900]], ['control 5', {'initial_bp': 500, 'index_path': [212, 537], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 700]]], [['regression: rate increment rounding', {'initial_bp': 300, 'index_path': [650, 250, 50, 537, 50], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 375, 575, 375]], ['regression: rate increment rounding, partial-repair probe', {'initial_bp': 450, 'index_path': [650, 212, 537, 50], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [900, 800, 750, 650]], ['control 1', {'initial_bp': 300, 'index_path': [400, 400, 537], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 675, 800]], ['control 2', {'initial_bp': 500, 'index_path': [537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [700]], ['control 3', {'initial_bp': 300, 'index_path': [250, 250, 250], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500, 500, 500]], ['control 4', {'initial_bp': 300, 'index_path': [400, 100, 400, 250, 50], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 400, 500, 525, 425]], ['control 5', {'initial_bp': 300, 'index_path': [700, 212], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [800, 700]]], [['regression: rate increment rounding', {'initial_bp': 450, 'index_path': [650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875]], ['regression: rate increment rounding, partial-repair probe', {'initial_bp': 500, 'index_path': [250, 537], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500, 600]], ['control 1', {'initial_bp': 300, 'index_path': [400, 537, 100], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 700, 500]], ['control 2', {'initial_bp': 500, 'index_path': [400, 212], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [650, 550]], ['control 3', {'initial_bp': 450, 'index_path': [250, 700, 212, 700, 650], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [500, 600, 500, 600, 700]], ['control 4', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500]], ['control 5', {'initial_bp': 300, 'index_path': [50, 537, 250, 100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [300, 400, 475, 375]]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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(x):
    rate = x['initial_bp']
    out = []
    life_max = x['initial_bp'] + x['lifetime_cap_bp']
    for i, idx in enumerate(x['index_path']):
        fi = idx + x['margin_bp']
        q, r = divmod(fi, x['round_to'])
        fi = (q + (1 if 2 * r > x['round_to'] else 0)) * x['round_to']
        cap = x['initial_cap_bp'] if i == 0 else x['periodic_cap_bp']
        new = max(rate - cap, min(fi, rate + cap))
        new = max(x['floor_bp'], min(new, life_max))
        out.append(new)
        rate = new
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: rate increment rounding', {'initial_bp': 500, 'index_path': [700, 50, 700, 50, 100], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875, 675, 875, 675, 475]], ['regression: rate increment rounding, partial-repair probe', {'initial_bp': 300, 'index_path': [100, 50, 250], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [400, 350, 550]], ['control 1', {'initial_bp': 500, 'index_path': [212, 100, 50, 250, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 400, 400, 500, 600]], ['control 2', {'initial_bp': 450, 'index_path': [250, 650, 100, 650, 650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 675]], ['control 3', {'initial_bp': 500, 'index_path': [650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [875]], ['control 4', {'initial_bp': 450, 'index_path': [50, 537, 400, 650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [375, 475, 575, 675]], ['control 5', {'initial_bp': 300, 'index_path': [650, 212, 100], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 500, 400]]], [['regression: rate increment rounding', {'initial_bp': 500, 'index_path': [537, 650, 250, 400, 537], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [700, 875, 675, 625, 750]], ['regression: rate increment rounding, partial-repair probe', {'initial_bp': 500, 'index_path': [50], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [350]], ['control 1', {'initial_bp': 450, 'index_path': [650, 50, 212], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [650, 550, 500]], ['control 2', {'initial_bp': 300, 'index_path': [650, 50, 700], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [800, 600, 800]], ['control 3', {'initial_bp': 450, 'index_path': [250, 100, 700], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 325, 525]], ['control 4', {'initial_bp': 500, 'index_path': [250, 400, 50, 700, 400], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 625]], ['control 5', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [525]]], [['regression: rate increment rounding', {'initial_bp': 300, 'index_path': [537, 700, 250], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [750, 850, 750]], ['regression: rate increment rounding, partial-repair probe', {'initial_bp': 450, 'index_path': [250, 250, 212], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 450]], ['control 1', {'initial_bp': 450, 'index_path': [212, 650, 50, 650], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [500, 700, 500, 700]], ['control 2', {'initial_bp': 450, 'index_path': [537, 50, 537], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [650, 550, 650]], ['control 3', {'initial_bp': 450, 'index_path': [100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400]], ['control 4', {'initial_bp': 500, 'index_path': [700, 250], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [1000, 900]], ['control 5', {'initial_bp': 500, 'index_path': [212, 537], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 700]]], [['regression: rate increment rounding', {'initial_bp': 300, 'index_path': [650, 250, 50, 537, 50], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 375, 575, 375]], ['regression: rate increment rounding, partial-repair probe', {'initial_bp': 450, 'index_path': [650, 212, 537, 50], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [900, 800, 750, 650]], ['control 1', {'initial_bp': 300, 'index_path': [400, 400, 537], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 675, 800]], ['control 2', {'initial_bp': 500, 'index_path': [537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [700]], ['control 3', {'initial_bp': 300, 'index_path': [250, 250, 250], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500, 500, 500]], ['control 4', {'initial_bp': 300, 'index_path': [400, 100, 400, 250, 50], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 400, 500, 525, 425]], ['control 5', {'initial_bp': 300, 'index_path': [700, 212], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [800, 700]]], [['regression: rate increment rounding', {'initial_bp': 450, 'index_path': [650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875]], ['regression: rate increment rounding, partial-repair probe', {'initial_bp': 500, 'index_path': [250, 537], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500, 600]], ['control 1', {'initial_bp': 300, 'index_path': [400, 537, 100], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 700, 500]], ['control 2', {'initial_bp': 500, 'index_path': [400, 212], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [650, 550]], ['control 3', {'initial_bp': 450, 'index_path': [250, 700, 212, 700, 650], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [500, 600, 500, 600, 700]], ['control 4', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500]], ['control 5', {'initial_bp': 300, 'index_path': [50, 537, 250, 100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [300, 400, 475, 375]]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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:
Fully indexed rates are always rounded up to the next increment.

x = {'initial_bp', 'index_path': index at each reset, 'margin_bp', 'round_to', 'initial_cap_bp', 'periodic_cap_bp', 'lifetime_cap_bp' (above initial), 'floor_bp'}. At each reset the fully indexed rate index + margin is rounded half-up to a multiple of round_to, limited to within the cap of the previous note rate (initial cap at the first reset, periodic afterwards, both directions), then limited to [floor_bp, initial + lifetime cap]. Return the list of note rates.

split: open-access


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

N = 1
observations = []
def solve(x):
    rate = x['initial_bp']
    out = []
    life_max = x['initial_bp'] + x['lifetime_cap_bp']
    for i, idx in enumerate(x['index_path']):
        fi = idx + x['margin_bp']
        q, r = divmod(fi, x['round_to'])
        fi = (q + (1 if 2 * r >= x['round_to'] else 0)) * x['round_to']
        cap = x['initial_cap_bp'] if i == 0 else x['periodic_cap_bp']
        new = max(rate - cap, min(fi, rate + cap))
        new = min(new, life_max)
        out.append(new)
        rate = new
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: floor application', {'initial_bp': 500, 'index_path': [212, 100, 50, 250, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 400, 400, 500, 600]], ['control 1', {'initial_bp': 450, 'index_path': [250, 650, 100, 650, 650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 675]], ['control 2', {'initial_bp': 500, 'index_path': [700, 50, 700, 50, 100], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875, 675, 875, 675, 475]], ['control 3', {'initial_bp': 500, 'index_path': [650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [875]], ['control 4', {'initial_bp': 450, 'index_path': [50, 537, 400, 650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [375, 475, 575, 675]], ['control 5', {'initial_bp': 300, 'index_path': [212, 212], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [475, 475]], ['control 6', {'initial_bp': 300, 'index_path': [100, 50, 250], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [400, 350, 550]]], [['regression: floor application', {'initial_bp': 450, 'index_path': [50], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [400]], ['control 1', {'initial_bp': 450, 'index_path': [650, 50, 212], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [650, 550, 500]], ['control 2', {'initial_bp': 300, 'index_path': [650, 50, 700], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [800, 600, 800]], ['control 3', {'initial_bp': 500, 'index_path': [537, 650, 250, 400, 537], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [700, 875, 675, 625, 750]], ['control 4', {'initial_bp': 450, 'index_path': [250, 100, 700], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 325, 525]], ['control 5', {'initial_bp': 450, 'index_path': [400, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [625, 825]], ['control 6', {'initial_bp': 500, 'index_path': [250, 400, 50, 700, 400], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 625]]], [['regression: floor application', {'initial_bp': 450, 'index_path': [100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400]], ['control 1', {'initial_bp': 450, 'index_path': [212, 650, 50, 650], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [500, 700, 500, 700]], ['control 2', {'initial_bp': 450, 'index_path': [250, 250, 212], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 450]], ['control 3', {'initial_bp': 300, 'index_path': [537, 700, 250], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [750, 850, 750]], ['control 4', {'initial_bp': 450, 'index_path': [537, 50, 537], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [650, 550, 650]], ['control 5', {'initial_bp': 500, 'index_path': [700, 250], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [1000, 900]], ['control 6', {'initial_bp': 500, 'index_path': [212, 537], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 700]]], [['regression: floor application', {'initial_bp': 500, 'index_path': [100], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [400]], ['control 1', {'initial_bp': 300, 'index_path': [650, 250, 50, 537, 50], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 375, 575, 375]], ['control 2', {'initial_bp': 300, 'index_path': [400, 400, 537], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 675, 800]], ['control 3', {'initial_bp': 450, 'index_path': [537, 250, 212, 212], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [650, 550, 450, 450]], ['control 4', {'initial_bp': 500, 'index_path': [537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [700]], ['control 5', {'initial_bp': 300, 'index_path': [250, 250, 250], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500, 500, 500]], ['control 6', {'initial_bp': 500, 'index_path': [100, 212, 100], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [350, 450, 350]]], [['regression: floor application', {'initial_bp': 300, 'index_path': [50, 650, 50, 250, 537], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400, 600, 400, 500, 700]], ['control 1', {'initial_bp': 450, 'index_path': [650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875]], ['control 2', {'initial_bp': 300, 'index_path': [400, 537, 100], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 700, 500]], ['control 3', {'initial_bp': 500, 'index_path': [400, 212], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [650, 550]], ['control 4', {'initial_bp': 450, 'index_path': [400, 537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [650, 775]], ['control 5', {'initial_bp': 450, 'index_path': [400, 50, 212, 250], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [675, 475, 475, 525]], ['control 6', {'initial_bp': 450, 'index_path': [250, 700, 212, 700, 650], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [500, 600, 500, 600, 700]]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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(x):
    rate = x['initial_bp']
    out = []
    life_max = x['initial_bp'] + x['lifetime_cap_bp']
    for i, idx in enumerate(x['index_path']):
        fi = idx + x['margin_bp']
        q, r = divmod(fi, x['round_to'])
        fi = (q + (1 if 2 * r >= x['round_to'] else 0)) * x['round_to']
        cap = x['initial_cap_bp'] if i == 0 else x['periodic_cap_bp']
        new = max(rate - cap, min(fi, rate + cap))
        new = max(x['floor_bp'] - x['margin_bp'], min(new, life_max))
        out.append(new)
        rate = new
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: floor application', {'initial_bp': 500, 'index_path': [212, 100, 50, 250, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 400, 400, 500, 600]], ['control 1', {'initial_bp': 450, 'index_path': [250, 650, 100, 650, 650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 675]], ['control 2', {'initial_bp': 500, 'index_path': [700, 50, 700, 50, 100], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875, 675, 875, 675, 475]], ['control 3', {'initial_bp': 500, 'index_path': [650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [875]], ['control 4', {'initial_bp': 450, 'index_path': [50, 537, 400, 650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [375, 475, 575, 675]], ['control 5', {'initial_bp': 300, 'index_path': [212, 212], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [475, 475]], ['control 6', {'initial_bp': 300, 'index_path': [100, 50, 250], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [400, 350, 550]]], [['regression: floor application', {'initial_bp': 450, 'index_path': [50], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [400]], ['control 1', {'initial_bp': 450, 'index_path': [650, 50, 212], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [650, 550, 500]], ['control 2', {'initial_bp': 300, 'index_path': [650, 50, 700], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [800, 600, 800]], ['control 3', {'initial_bp': 500, 'index_path': [537, 650, 250, 400, 537], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [700, 875, 675, 625, 750]], ['control 4', {'initial_bp': 450, 'index_path': [250, 100, 700], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 325, 525]], ['control 5', {'initial_bp': 450, 'index_path': [400, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [625, 825]], ['control 6', {'initial_bp': 500, 'index_path': [250, 400, 50, 700, 400], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 625]]], [['regression: floor application', {'initial_bp': 450, 'index_path': [100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400]], ['control 1', {'initial_bp': 450, 'index_path': [212, 650, 50, 650], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [500, 700, 500, 700]], ['control 2', {'initial_bp': 450, 'index_path': [250, 250, 212], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 450]], ['control 3', {'initial_bp': 300, 'index_path': [537, 700, 250], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [750, 850, 750]], ['control 4', {'initial_bp': 450, 'index_path': [537, 50, 537], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [650, 550, 650]], ['control 5', {'initial_bp': 500, 'index_path': [700, 250], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [1000, 900]], ['control 6', {'initial_bp': 500, 'index_path': [212, 537], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 700]]], [['regression: floor application', {'initial_bp': 500, 'index_path': [100], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [400]], ['control 1', {'initial_bp': 300, 'index_path': [650, 250, 50, 537, 50], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 375, 575, 375]], ['control 2', {'initial_bp': 300, 'index_path': [400, 400, 537], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 675, 800]], ['control 3', {'initial_bp': 450, 'index_path': [537, 250, 212, 212], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [650, 550, 450, 450]], ['control 4', {'initial_bp': 500, 'index_path': [537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [700]], ['control 5', {'initial_bp': 300, 'index_path': [250, 250, 250], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500, 500, 500]], ['control 6', {'initial_bp': 500, 'index_path': [100, 212, 100], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [350, 450, 350]]], [['regression: floor application', {'initial_bp': 300, 'index_path': [50, 650, 50, 250, 537], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400, 600, 400, 500, 700]], ['control 1', {'initial_bp': 450, 'index_path': [650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875]], ['control 2', {'initial_bp': 300, 'index_path': [400, 537, 100], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 700, 500]], ['control 3', {'initial_bp': 500, 'index_path': [400, 212], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [650, 550]], ['control 4', {'initial_bp': 450, 'index_path': [400, 537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [650, 775]], ['control 5', {'initial_bp': 450, 'index_path': [400, 50, 212, 250], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [675, 475, 475, 525]], ['control 6', {'initial_bp': 450, 'index_path': [250, 700, 212, 700, 650], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [500, 600, 500, 600, 700]]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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:
Note rates fall below the contractual floor.

x = {'initial_bp', 'index_path': index at each reset, 'margin_bp', 'round_to', 'initial_cap_bp', 'periodic_cap_bp', 'lifetime_cap_bp' (above initial), 'floor_bp'}. At each reset the fully indexed rate index + margin is rounded half-up to a multiple of round_to, limited to within the cap of the previous note rate (initial cap at the first reset, periodic afterwards, both directions), then limited to [floor_bp, initial + lifetime cap]. Return the list of note rates.

split: open-access


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

N = 1
observations = []
def solve(x):
    rate = x['initial_bp']
    out = []
    life_max = x['initial_bp'] + x['lifetime_cap_bp']
    for i, idx in enumerate(x['index_path']):
        fi = idx + x['margin_bp']
        q, r = divmod(fi, x['round_to'])
        fi = (q + (1 if 2 * r >= x['round_to'] else 0)) * x['round_to']
        cap = x['initial_cap_bp'] if i == 0 else x['periodic_cap_bp']
        new = max(rate - cap, min(fi, rate + cap))
        new = max(x['floor_bp'], min(new, life_max))
        out.append(new)
        rate = fi
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: cap reference rate', {'initial_bp': 500, 'index_path': [212, 100, 50, 250, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 400, 400, 500, 600]], ['regression: cap reference rate, partial-repair probe', {'initial_bp': 450, 'index_path': [250, 650, 100, 650, 650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 675]], ['control 1', {'initial_bp': 500, 'index_path': [650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [875]], ['control 2', {'initial_bp': 300, 'index_path': [212, 212], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [475, 475]], ['control 3', {'initial_bp': 300, 'index_path': [100, 50, 250], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [400, 350, 550]], ['control 4', {'initial_bp': 450, 'index_path': [50, 100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [300, 325]], ['control 5', {'initial_bp': 500, 'index_path': [700], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [700]]], [['regression: cap reference rate', {'initial_bp': 450, 'index_path': [650, 50, 212], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [650, 550, 500]], ['control 1', {'initial_bp': 500, 'index_path': [537, 650, 250, 400, 537], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [700, 875, 675, 625, 750]], ['control 2', {'initial_bp': 450, 'index_path': [250, 100, 700], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 325, 525]], ['control 3', {'initial_bp': 450, 'index_path': [400, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [625, 825]], ['control 4', {'initial_bp': 500, 'index_path': [212], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [375]], ['control 5', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [525]], ['control 6', {'initial_bp': 450, 'index_path': [50], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [400]]], [['regression: cap reference rate', {'initial_bp': 450, 'index_path': [212, 650, 50, 650], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [500, 700, 500, 700]], ['control 1', {'initial_bp': 450, 'index_path': [250, 250, 212], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 450]], ['control 2', {'initial_bp': 450, 'index_path': [100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400]], ['control 3', {'initial_bp': 500, 'index_path': [700, 250], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [1000, 900]], ['control 4', {'initial_bp': 500, 'index_path': [212, 537], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 700]], ['control 5', {'initial_bp': 450, 'index_path': [400, 50], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [625, 425]], ['control 6', {'initial_bp': 500, 'index_path': [700], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [1000]]], [['regression: cap reference rate', {'initial_bp': 300, 'index_path': [650, 250, 50, 537, 50], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 375, 575, 375]], ['control 1', {'initial_bp': 300, 'index_path': [400, 400, 537], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 675, 800]], ['control 2', {'initial_bp': 500, 'index_path': [537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [700]], ['control 3', {'initial_bp': 300, 'index_path': [250, 250, 250], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500, 500, 500]], ['control 4', {'initial_bp': 500, 'index_path': [100, 212, 100], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [350, 450, 350]], ['control 5', {'initial_bp': 500, 'index_path': [100], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [400]], ['control 6', {'initial_bp': 500, 'index_path': [250, 650], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [525, 725]]], [['regression: cap reference rate', {'initial_bp': 300, 'index_path': [400, 537, 100], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 700, 500]], ['control 1', {'initial_bp': 450, 'index_path': [650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875]], ['control 2', {'initial_bp': 500, 'index_path': [400, 212], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [650, 550]], ['control 3', {'initial_bp': 450, 'index_path': [400, 537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [650, 775]], ['control 4', {'initial_bp': 450, 'index_path': [400, 50, 212, 250], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [675, 475, 475, 525]], ['control 5', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500]], ['control 6', {'initial_bp': 300, 'index_path': [50, 50], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400, 400]]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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(x):
    rate = x['initial_bp']
    out = []
    life_max = x['initial_bp'] + x['lifetime_cap_bp']
    for i, idx in enumerate(x['index_path']):
        fi = idx + x['margin_bp']
        q, r = divmod(fi, x['round_to'])
        fi = (q + (1 if 2 * r >= x['round_to'] else 0)) * x['round_to']
        cap = x['initial_cap_bp'] if i == 0 else x['periodic_cap_bp']
        new = max(rate - cap, min(fi, rate + cap))
        new = max(x['floor_bp'], min(new, life_max))
        out.append(new)
        rate = x['initial_bp']
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: cap reference rate', {'initial_bp': 500, 'index_path': [212, 100, 50, 250, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 400, 400, 500, 600]], ['regression: cap reference rate, partial-repair probe', {'initial_bp': 450, 'index_path': [250, 650, 100, 650, 650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 575, 475, 575, 675]], ['control 1', {'initial_bp': 500, 'index_path': [650], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [875]], ['control 2', {'initial_bp': 300, 'index_path': [212, 212], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [475, 475]], ['control 3', {'initial_bp': 300, 'index_path': [100, 50, 250], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [400, 350, 550]], ['control 4', {'initial_bp': 450, 'index_path': [50, 100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [300, 325]], ['control 5', {'initial_bp': 500, 'index_path': [700], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [700]]], [['regression: cap reference rate', {'initial_bp': 450, 'index_path': [650, 50, 212], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [650, 550, 500]], ['control 1', {'initial_bp': 500, 'index_path': [537, 650, 250, 400, 537], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [700, 875, 675, 625, 750]], ['control 2', {'initial_bp': 450, 'index_path': [250, 100, 700], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [475, 325, 525]], ['control 3', {'initial_bp': 450, 'index_path': [400, 700], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [625, 825]], ['control 4', {'initial_bp': 500, 'index_path': [212], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [375]], ['control 5', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [525]], ['control 6', {'initial_bp': 450, 'index_path': [50], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [400]]], [['regression: cap reference rate', {'initial_bp': 450, 'index_path': [212, 650, 50, 650], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [500, 700, 500, 700]], ['control 1', {'initial_bp': 450, 'index_path': [250, 250, 212], 'margin_bp': 225, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 450]], ['control 2', {'initial_bp': 450, 'index_path': [100], 'margin_bp': 225, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400]], ['control 3', {'initial_bp': 500, 'index_path': [700, 250], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [1000, 900]], ['control 4', {'initial_bp': 500, 'index_path': [212, 537], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 700]], ['control 5', {'initial_bp': 450, 'index_path': [400, 50], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [625, 425]], ['control 6', {'initial_bp': 500, 'index_path': [700], 'margin_bp': 275, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [1000]]], [['regression: cap reference rate', {'initial_bp': 300, 'index_path': [650, 250, 50, 537, 50], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [500, 500, 375, 575, 375]], ['control 1', {'initial_bp': 300, 'index_path': [400, 400, 537], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [500, 675, 800]], ['control 2', {'initial_bp': 500, 'index_path': [537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [700]], ['control 3', {'initial_bp': 300, 'index_path': [250, 250, 250], 'margin_bp': 250, 'round_to': 50, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500, 500, 500]], ['control 4', {'initial_bp': 500, 'index_path': [100, 212, 100], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 225}, [350, 450, 350]], ['control 5', {'initial_bp': 500, 'index_path': [100], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [400]], ['control 6', {'initial_bp': 500, 'index_path': [250, 650], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [525, 725]]], [['regression: cap reference rate', {'initial_bp': 300, 'index_path': [400, 537, 100], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [500, 700, 500]], ['control 1', {'initial_bp': 450, 'index_path': [650], 'margin_bp': 275, 'round_to': 125, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 300}, [875]], ['control 2', {'initial_bp': 500, 'index_path': [400, 212], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 100, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [650, 550]], ['control 3', {'initial_bp': 450, 'index_path': [400, 537], 'margin_bp': 250, 'round_to': 25, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 400}, [650, 775]], ['control 4', {'initial_bp': 450, 'index_path': [400, 50, 212, 250], 'margin_bp': 275, 'round_to': 25, 'initial_cap_bp': 500, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 225}, [675, 475, 475, 525]], ['control 5', {'initial_bp': 300, 'index_path': [250], 'margin_bp': 225, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 600, 'floor_bp': 300}, [500]], ['control 6', {'initial_bp': 300, 'index_path': [50, 50], 'margin_bp': 250, 'round_to': 125, 'initial_cap_bp': 200, 'periodic_cap_bp': 200, 'lifetime_cap_bp': 500, 'floor_bp': 400}, [400, 400]]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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:
Later resets jump by more than the periodic cap from the prior note rate.

x = {'initial_bp', 'index_path': index at each reset, 'margin_bp', 'round_to', 'initial_cap_bp', 'periodic_cap_bp', 'lifetime_cap_bp' (above initial), 'floor_bp'}. At each reset the fully indexed rate index + margin is rounded half-up to a multiple of round_to, limited to within the cap of the previous note rate (initial cap at the first reset, periodic afterwards, both directions), then limited to [floor_bp, initial + lifetime cap]. Return the list of note rates.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    def rnd(n, d):
        q, r = divmod(n, d)
        return q + (1 if 2 * r >= d else 0)
    def level(P, n):
        if n <= 0 or P <= 0:
            return 0
        if bp == 0:
            exact = Fraction(P, n)
        else:
            r = Fraction(bp, 120000)
            exact = P * r / (1 - (1 + r) ** -n)
        return math.floor(exact + Fraction(1, 2))
    bp = x['rate_bp']
    P = x['principal']
    pay = level(P, x['term_months'])
    last_k = min(x['term_months'], x['amort_months'])
    bal = P
    total = 0
    final = 0
    for k in range(1, last_k + 1):
        interest = rnd(bal * bp, 120000)
        total += interest
        if k == last_k:
            final = bal + interest
        else:
            bal -= pay - interest
    return {'payment': pay, 'final_payment': final, 'balloon_excess': final - pay, 'total_interest': total}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: amortization basis', {'principal': 100000, 'rate_bp': 0, 'amort_months': 5, 'term_months': 3}, {'payment': 20000, 'final_payment': 60000, 'balloon_excess': 40000, 'total_interest': 0}], ['regression: amortization basis, partial-repair probe', {'principal': 55555, 'rate_bp': 600, 'amort_months': 12, 'term_months': 84}, {'payment': 4781, 'final_payment': 4786, 'balloon_excess': 5, 'total_interest': 1822}], ['control 1', {'principal': 100000, 'rate_bp': 725, 'amort_months': 5, 'term_months': 5}, {'payment': 20364, 'final_payment': 20364, 'balloon_excess': 0, 'total_interest': 1820}], ['control 2', {'principal': 55555, 'rate_bp': 600, 'amort_months': 5, 'term_months': 5}, {'payment': 11278, 'final_payment': 11280, 'balloon_excess': 2, 'total_interest': 837}], ['control 3', {'principal': 1000000, 'rate_bp': 0, 'amort_months': 60, 'term_months': 60}, {'payment': 16667, 'final_payment': 16647, 'balloon_excess': -20, 'total_interest': 0}], ['control 4', {'principal': 100000, 'rate_bp': 725, 'amort_months': 60, 'term_months': 60}, {'payment': 1992, 'final_payment': 1987, 'balloon_excess': -5, 'total_interest': 19515}], ['control 5', {'principal': 1000000, 'rate_bp': 0, 'amort_months': 12, 'term_months': 12}, {'payment': 83333, 'final_payment': 83337, 'balloon_excess': 4, 'total_interest': 0}]], [['regression: amortization basis', {'principal': 100000, 'rate_bp': 0, 'amort_months': 12, 'term_months': 5}, {'payment': 8333, 'final_payment': 66668, 'balloon_excess': 58335, 'total_interest': 0}], ['regression: amortization basis, partial-repair probe', {'principal': 55555, 'rate_bp': 600, 'amort_months': 12, 'term_months': 60}, {'payment': 4781, 'final_payment': 4786, 'balloon_excess': 5, 'total_interest': 1822}], ['control 1', {'principal': 100000, 'rate_bp': 600, 'amort_months': 5, 'term_months': 5}, {'payment': 20301, 'final_payment': 20300, 'balloon_excess': -1, 'total_interest': 1504}], ['control 2', {'principal': 100000, 'rate_bp': 1200, 'amort_months': 60, 'term_months': 60}, {'payment': 2224, 'final_payment': 2262, 'balloon_excess': 38, 'total_interest': 33478}], ['control 3', {'principal': 100000, 'rate_bp': 0, 'amort_months': 60, 'term_months': 60}, {'payment': 1667, 'final_payment': 1647, 'balloon_excess': -20, 'total_interest': 0}], ['control 4', {'principal': 1000000, 'rate_bp': 600, 'amort_months': 60, 'term_months': 60}, {'payment': 19333, 'final_payment': 19321, 'balloon_excess': -12, 'total_interest': 159968}], ['control 5', {'principal': 55555, 'rate_bp': 725, 'amort_months': 5, 'term_months': 5}, {'payment': 11313, 'final_payment': 11314, 'balloon_excess': 1, 'total_interest': 1011}]], [['regression: amortization basis', {'principal': 100000, 'rate_bp': 0, 'amort_months': 5, 'term_months': 3}, {'payment': 20000, 'final_payment': 60000, 'balloon_excess': 40000, 'total_interest': 0}], ['regression: amortization basis, partial-repair probe', {'principal': 1000000, 'rate_bp': 1200, 'amort_months': 5, 'term_months': 60}, {'payment': 206040, 'final_payment': 206040, 'balloon_excess': 0, 'total_interest': 30200}], ['control 1', {'principal': 100000, 'rate_bp': 1200, 'amort_months': 12, 'term_months': 12}, {'payment': 8885, 'final_payment': 8884, 'balloon_excess': -1, 'total_interest': 6619}], ['control 2', {'principal': 100000, 'rate_bp': 0, 'amort_months': 12, 'term_months': 12}, {'payment': 8333, 'final_payment': 8337, 'balloon_excess': 4, 'total_interest': 0}], ['control 3', {'principal': 1000000, 'rate_bp': 1200, 'amort_months': 5, 'term_months': 5}, {'payment': 206040, 'final_payment': 206040, 'balloon_excess': 0, 'total_interest': 30200}], ['control 4', {'principal': 55555, 'rate_bp': 725, 'amort_months': 12, 'term_months': 12}, {'payment': 4813, 'final_payment': 4819, 'balloon_excess': 6, 'total_interest': 2207}], ['control 5', {'principal': 55555, 'rate_bp': 0, 'amort_months': 5, 'term_months': 5}, {'payment': 11111, 'final_payment': 11111, 'balloon_excess': 0, 'total_interest': 0}]], [['regression: amortization basis', {'principal': 1000000, 'rate_bp': 725, 'amort_months': 360, 'term_months': 12}, {'payment': 6822, 'final_payment': 997140, 'balloon_excess': 990318, 'total_interest': 72182}], ['regression: amortization basis, partial-repair probe', {'principal': 55555, 'rate_bp': 0, 'amort_months': 5, 'term_months': 84}, {'payment': 11111, 'final_payment': 11111, 'balloon_excess': 0, 'total_interest': 0}], ['control 1', {'principal': 1000000, 'rate_bp': 600, 'amort_months': 5, 'term_months': 5}, {'payment': 203010, 'final_payment': 203010, 'balloon_excess': 0, 'total_interest': 15050}], ['control 2', {'principal': 1000000, 'rate_bp': 1200, 'amort_months': 5, 'term_months': 5}, {'payment': 206040, 'final_payment': 206040, 'balloon_excess': 0, 'total_interest': 30200}], ['control 3', {'principal': 100000, 'rate_bp': 0, 'amort_months': 60, 'term_months': 60}, {'payment': 1667, 'final_payment': 1647, 'balloon_excess': -20, 'total_interest': 0}], ['control 4', {'principal': 1000000, 'rate_bp': 0, 'amort_months': 12, 'term_months': 12}, {'payment': 83333, 'final_payment': 83337, 'balloon_excess': 4, 'total_interest': 0}], ['control 5', {'principal': 1000000, 'rate_bp': 1200, 'amort_months': 60, 'term_months': 60}, {'payment': 22244, 'final_payment': 22281, 'balloon_excess': 37, 'total_interest': 334677}]], [['regression: amortization basis', {'principal': 3000000, 'rate_bp': 1200, 'amort_months': 60, 'term_months': 12}, {'payment': 66733, 'final_payment': 2600867, 'balloon_excess': 2534134, 'total_interest': 334930}], ['regression: amortization basis, partial-repair probe', {'principal': 55555, 'rate_bp': 1200, 'amort_months': 12, 'term_months': 60}, {'payment': 4936, 'final_payment': 4938, 'balloon_excess': 2, 'total_interest': 3679}], ['control 1', {'principal': 100000, 'rate_bp': 600, 'amort_months': 60, 'term_months': 60}, {'payment': 1933, 'final_payment': 1952, 'balloon_excess': 19, 'total_interest': 15999}], ['control 2', {'principal': 55555, 'rate_bp': 0, 'amort_months': 60, 'term_months': 60}, {'payment': 926, 'final_payment': 921, 'balloon_excess': -5, 'total_interest': 0}], ['control 3', {'principal': 100000, 'rate_bp': 1200, 'amort_months': 12, 'term_months': 12}, {'payment': 8885, 'final_payment': 8884, 'balloon_excess': -1, 'total_interest': 6619}], ['control 4', {'principal': 3000000, 'rate_bp': 725, 'amort_months': 5, 'term_months': 5}, {'payment': 610919, 'final_payment': 610918, 'balloon_excess': -1, 'total_interest': 54594}], ['control 5', {'principal': 1000000, 'rate_bp': 725, 'amort_months': 5, 'term_months': 5}, {'payment': 203640, 'final_payment': 203639, 'balloon_excess': -1, 'total_interest': 18199}]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    def rnd(n, d):
        q, r = divmod(n, d)
        return q + (1 if 2 * r >= d else 0)
    def level(P, n):
        if n <= 0 or P <= 0:
            return 0
        if bp == 0:
            exact = Fraction(P, n)
        else:
            r = Fraction(bp, 120000)
            exact = P * r / (1 - (1 + r) ** -n)
        return math.floor(exact + Fraction(1, 2))
    bp = x['rate_bp']
    P = x['principal']
    pay = level(P, x['amort_months']) if x['amort_months'] > x['term_months'] else level(P, x['term_months'])
    last_k = min(x['term_months'], x['amort_months'])
    bal = P
    total = 0
    final = 0
    for k in range(1, last_k + 1):
        interest = rnd(bal * bp, 120000)
        total += interest
        if k == last_k:
            final = bal + interest
        else:
            bal -= pay - interest
    return {'payment': pay, 'final_payment': final, 'balloon_excess': final - pay, 'total_interest': total}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: amortization basis', {'principal': 100000, 'rate_bp': 0, 'amort_months': 5, 'term_months': 3}, {'payment': 20000, 'final_payment': 60000, 'balloon_excess': 40000, 'total_interest': 0}], ['regression: amortization basis, partial-repair probe', {'principal': 55555, 'rate_bp': 600, 'amort_months': 12, 'term_months': 84}, {'payment': 4781, 'final_payment': 4786, 'balloon_excess': 5, 'total_interest': 1822}], ['control 1', {'principal': 100000, 'rate_bp': 725, 'amort_months': 5, 'term_months': 5}, {'payment': 20364, 'final_payment': 20364, 'balloon_excess': 0, 'total_interest': 1820}], ['control 2', {'principal': 55555, 'rate_bp': 600, 'amort_months': 5, 'term_months': 5}, {'payment': 11278, 'final_payment': 11280, 'balloon_excess': 2, 'total_interest': 837}], ['control 3', {'principal': 1000000, 'rate_bp': 0, 'amort_months': 60, 'term_months': 60}, {'payment': 16667, 'final_payment': 16647, 'balloon_excess': -20, 'total_interest': 0}], ['control 4', {'principal': 100000, 'rate_bp': 725, 'amort_months': 60, 'term_months': 60}, {'payment': 1992, 'final_payment': 1987, 'balloon_excess': -5, 'total_interest': 19515}], ['control 5', {'principal': 1000000, 'rate_bp': 0, 'amort_months': 12, 'term_months': 12}, {'payment': 83333, 'final_payment': 83337, 'balloon_excess': 4, 'total_interest': 0}]], [['regression: amortization basis', {'principal': 100000, 'rate_bp': 0, 'amort_months': 12, 'term_months': 5}, {'payment': 8333, 'final_payment': 66668, 'balloon_excess': 58335, 'total_interest': 0}], ['regression: amortization basis, partial-repair probe', {'principal': 55555, 'rate_bp': 600, 'amort_months': 12, 'term_months': 60}, {'payment': 4781, 'final_payment': 4786, 'balloon_excess': 5, 'total_interest': 1822}], ['control 1', {'principal': 100000, 'rate_bp': 600, 'amort_months': 5, 'term_months': 5}, {'payment': 20301, 'final_payment': 20300, 'balloon_excess': -1, 'total_interest': 1504}], ['control 2', {'principal': 100000, 'rate_bp': 1200, 'amort_months': 60, 'term_months': 60}, {'payment': 2224, 'final_payment': 2262, 'balloon_excess': 38, 'total_interest': 33478}], ['control 3', {'principal': 100000, 'rate_bp': 0, 'amort_months': 60, 'term_months': 60}, {'payment': 1667, 'final_payment': 1647, 'balloon_excess': -20, 'total_interest': 0}], ['control 4', {'principal': 1000000, 'rate_bp': 600, 'amort_months': 60, 'term_months': 60}, {'payment': 19333, 'final_payment': 19321, 'balloon_excess': -12, 'total_interest': 159968}], ['control 5', {'principal': 55555, 'rate_bp': 725, 'amort_months': 5, 'term_months': 5}, {'payment': 11313, 'final_payment': 11314, 'balloon_excess': 1, 'total_interest': 1011}]], [['regression: amortization basis', {'principal': 100000, 'rate_bp': 0, 'amort_months': 5, 'term_months': 3}, {'payment': 20000, 'final_payment': 60000, 'balloon_excess': 40000, 'total_interest': 0}], ['regression: amortization basis, partial-repair probe', {'principal': 1000000, 'rate_bp': 1200, 'amort_months': 5, 'term_months': 60}, {'payment': 206040, 'final_payment': 206040, 'balloon_excess': 0, 'total_interest': 30200}], ['control 1', {'principal': 100000, 'rate_bp': 1200, 'amort_months': 12, 'term_months': 12}, {'payment': 8885, 'final_payment': 8884, 'balloon_excess': -1, 'total_interest': 6619}], ['control 2', {'principal': 100000, 'rate_bp': 0, 'amort_months': 12, 'term_months': 12}, {'payment': 8333, 'final_payment': 8337, 'balloon_excess': 4, 'total_interest': 0}], ['control 3', {'principal': 1000000, 'rate_bp': 1200, 'amort_months': 5, 'term_months': 5}, {'payment': 206040, 'final_payment': 206040, 'balloon_excess': 0, 'total_interest': 30200}], ['control 4', {'principal': 55555, 'rate_bp': 725, 'amort_months': 12, 'term_months': 12}, {'payment': 4813, 'final_payment': 4819, 'balloon_excess': 6, 'total_interest': 2207}], ['control 5', {'principal': 55555, 'rate_bp': 0, 'amort_months': 5, 'term_months': 5}, {'payment': 11111, 'final_payment': 11111, 'balloon_excess': 0, 'total_interest': 0}]], [['regression: amortization basis', {'principal': 1000000, 'rate_bp': 725, 'amort_months': 360, 'term_months': 12}, {'payment': 6822, 'final_payment': 997140, 'balloon_excess': 990318, 'total_interest': 72182}], ['regression: amortization basis, partial-repair probe', {'principal': 55555, 'rate_bp': 0, 'amort_months': 5, 'term_months': 84}, {'payment': 11111, 'final_payment': 11111, 'balloon_excess': 0, 'total_interest': 0}], ['control 1', {'principal': 1000000, 'rate_bp': 600, 'amort_months': 5, 'term_months': 5}, {'payment': 203010, 'final_payment': 203010, 'balloon_excess': 0, 'total_interest': 15050}], ['control 2', {'principal': 1000000, 'rate_bp': 1200, 'amort_months': 5, 'term_months': 5}, {'payment': 206040, 'final_payment': 206040, 'balloon_excess': 0, 'total_interest': 30200}], ['control 3', {'principal': 100000, 'rate_bp': 0, 'amort_months': 60, 'term_months': 60}, {'payment': 1667, 'final_payment': 1647, 'balloon_excess': -20, 'total_interest': 0}], ['control 4', {'principal': 1000000, 'rate_bp': 0, 'amort_months': 12, 'term_months': 12}, {'payment': 83333, 'final_payment': 83337, 'balloon_excess': 4, 'total_interest': 0}], ['control 5', {'principal': 1000000, 'rate_bp': 1200, 'amort_months': 60, 'term_months': 60}, {'payment': 22244, 'final_payment': 22281, 'balloon_excess': 37, 'total_interest': 334677}]], [['regression: amortization basis', {'principal': 3000000, 'rate_bp': 1200, 'amort_months': 60, 'term_months': 12}, {'payment': 66733, 'final_payment': 2600867, 'balloon_excess': 2534134, 'total_interest': 334930}], ['regression: amortization basis, partial-repair probe', {'principal': 55555, 'rate_bp': 1200, 'amort_months': 12, 'term_months': 60}, {'payment': 4936, 'final_payment': 4938, 'balloon_excess': 2, 'total_interest': 3679}], ['control 1', {'principal': 100000, 'rate_bp': 600, 'amort_months': 60, 'term_months': 60}, {'payment': 1933, 'final_payment': 1952, 'balloon_excess': 19, 'total_interest': 15999}], ['control 2', {'principal': 55555, 'rate_bp': 0, 'amort_months': 60, 'term_months': 60}, {'payment': 926, 'final_payment': 921, 'balloon_excess': -5, 'total_interest': 0}], ['control 3', {'principal': 100000, 'rate_bp': 1200, 'amort_months': 12, 'term_months': 12}, {'payment': 8885, 'final_payment': 8884, 'balloon_excess': -1, 'total_interest': 6619}], ['control 4', {'principal': 3000000, 'rate_bp': 725, 'amort_months': 5, 'term_months': 5}, {'payment': 610919, 'final_payment': 610918, 'balloon_excess': -1, 'total_interest': 54594}], ['control 5', {'principal': 1000000, 'rate_bp': 725, 'amort_months': 5, 'term_months': 5}, {'payment': 203640, 'final_payment': 203639, 'balloon_excess': -1, 'total_interest': 18199}]]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'raised ' + type(exc).__name__
    check(label, actual, 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:
Balloon loans are quoted fully amortizing payments over the short term.

x = {'principal', 'rate_bp', 'amort_months', 'term_months'}. The level payment amortizes over amort_months (exact annuity, half-up). Payments run to the earlier of term and amortization end; the last one pays balance + interest (the balloon). Monthly interest is round_half_up(balance*bp/120000). Return {'payment', 'final_payment', 'balloon_excess': final - payment, 'total_interest'}.

split: open-access