broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    s=x['start']; e=x['end']; T=e-s
    def r(v): return math.floor(v+Fraction(1,2)) if v>=0 else -math.floor(-v+Fraction(1,2))
    cur=x['annual']; out=[]; last=s
    for d,new in x['endorsements']:
        if d<s or d>e or d<last: return 'invalid endorsement date'
        out.append(r(Fraction((new-cur)*(e-d),T)))
        cur=new; last=d
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['single increase', {'start': 2912, 'end': 3277, 'annual': 228520, 'endorsements': [[3043, 390228]]}, [103670]], ['increase then decrease', {'start': 477, 'end': 842, 'annual': 136883, 'endorsements': [[562, 340860], [681, 77377]]}, [156476, -116221]], ['decrease then partial restore', {'start': 2037, 'end': 2402, 'annual': 100000, 'endorsements': [[2109, 40001], [2277, 63890]]}, [-48164, 8181]], ['leap-year term', {'start': 2320, 'end': 2686, 'annual': 138690, 'endorsements': [[2497, 161560]]}, [11810]], ['six-month term', {'start': 2269, 'end': 2451, 'annual': 114166, 'endorsements': [[2418, 400299], [2439, 379739]]}, [51881, -1356]], ['endorsement on expiry rejected', {'start': 286, 'end': 651, 'annual': 174243, 'endorsements': [[651, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 962, 'end': 1327, 'annual': 166624, 'endorsements': [[961, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 251, 'end': 616, 'annual': 164047, 'endorsements': [[451, 200000], [351, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 579, 'end': 944, 'annual': 88017, 'endorsements': [[579, 316996]]}, [228979]], ['same-day endorsements', {'start': 17, 'end': 382, 'annual': 194026, 'endorsements': [[137, 250000], [137, 260000]]}, [37572, 6712]], ['last day endorsement', {'start': 2889, 'end': 3254, 'annual': 100000, 'endorsements': [[3253, 255567]]}, [426]]], [['single increase', {'start': 2490, 'end': 2855, 'annual': 104092, 'endorsements': [[2682, 358418]]}, [120544]], ['increase then decrease', {'start': 1761, 'end': 2126, 'annual': 95155, 'endorsements': [[1839, 390602], [1949, 60898]]}, [232310, -159884]], ['decrease then partial restore', {'start': 2809, 'end': 3174, 'annual': 100000, 'endorsements': [[2849, 40002], [3041, 65761]]}, [-53423, 9386]], ['leap-year term', {'start': 2789, 'end': 3155, 'annual': 136600, 'endorsements': [[3052, 310248]]}, [48868]], ['six-month term', {'start': 1197, 'end': 1379, 'annual': 163268, 'endorsements': [[1271, 255330], [1367, 168424]]}, [54630, -5730]], ['endorsement on expiry rejected', {'start': 48, 'end': 413, 'annual': 192511, 'endorsements': [[413, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1771, 'end': 2136, 'annual': 162702, 'endorsements': [[1770, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2865, 'end': 3230, 'annual': 261177, 'endorsements': [[3065, 200000], [2965, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 1467, 'end': 1832, 'annual': 116027, 'endorsements': [[1467, 190089]]}, [74062]], ['same-day endorsements', {'start': 847, 'end': 1212, 'annual': 109565, 'endorsements': [[967, 250000], [967, 260000]]}, [94265, 6712]], ['last day endorsement', {'start': 2776, 'end': 3141, 'annual': 100000, 'endorsements': [[3140, 396043]]}, [811]]], [['single increase', {'start': 1206, 'end': 1571, 'annual': 166000, 'endorsements': [[1276, 393494]]}, [183865]], ['increase then decrease', {'start': 749, 'end': 1114, 'annual': 280762, 'endorsements': [[848, 343990], [953, 67369]]}, [46078, -122016]], ['decrease then partial restore', {'start': 766, 'end': 1131, 'annual': 100000, 'endorsements': [[803, 40003], [1051, 69438]]}, [-53915, 6452]], ['leap-year term', {'start': 2028, 'end': 2394, 'annual': 148609, 'endorsements': [[2319, 100348]]}, [-9890]], ['six-month term', {'start': 1944, 'end': 2126, 'annual': 124458, 'endorsements': [[2010, 171861], [2114, 388840]]}, [30213, 14306]], ['endorsement on expiry rejected', {'start': 1174, 'end': 1539, 'annual': 115160, 'endorsements': [[1539, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 2665, 'end': 3030, 'annual': 152976, 'endorsements': [[2664, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1602, 'end': 1967, 'annual': 240101, 'endorsements': [[1802, 200000], [1702, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 908, 'end': 1273, 'annual': 148941, 'endorsements': [[908, 436896]]}, [287955]], ['same-day endorsements', {'start': 1319, 'end': 1684, 'annual': 113258, 'endorsements': [[1439, 250000], [1439, 260000]]}, [91786, 6712]], ['last day endorsement', {'start': 2821, 'end': 3186, 'annual': 100000, 'endorsements': [[3185, 367523]]}, [733]]], [['single increase', {'start': 2447, 'end': 2812, 'annual': 190688, 'endorsements': [[2655, 312597]]}, [52438]], ['increase then decrease', {'start': 1314, 'end': 1679, 'annual': 268062, 'endorsements': [[1335, 344123], [1518, 58352]]}, [71685, -126052]], ['decrease then partial restore', {'start': 1117, 'end': 1482, 'annual': 100000, 'endorsements': [[1159, 40004], [1334, 61238]]}, [-53092, 8610]], ['leap-year term', {'start': 1273, 'end': 1639, 'annual': 241312, 'endorsements': [[1536, 193555]]}, [-13440]], ['six-month term', {'start': 49, 'end': 231, 'annual': 80756, 'endorsements': [[79, 411368], [219, 276361]]}, [276116, -8902]], ['endorsement on expiry rejected', {'start': 2167, 'end': 2532, 'annual': 216523, 'endorsements': [[2532, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1680, 'end': 2045, 'annual': 258325, 'endorsements': [[1679, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2653, 'end': 3018, 'annual': 115795, 'endorsements': [[2853, 200000], [2753, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2438, 'end': 2803, 'annual': 251511, 'endorsements': [[2438, 112887]]}, [-138624]], ['same-day endorsements', {'start': 1751, 'end': 2116, 'annual': 210625, 'endorsements': [[1871, 250000], [1871, 260000]]}, [26430, 6712]], ['last day endorsement', {'start': 1049, 'end': 1414, 'annual': 100000, 'endorsements': [[1413, 290691]]}, [522]]], [['single increase', {'start': 567, 'end': 932, 'annual': 242069, 'endorsements': [[864, 340392]]}, [18318]], ['increase then decrease', {'start': 2519, 'end': 2884, 'annual': 179314, 'endorsements': [[2537, 319903], [2726, 81013]]}, [133656, -103410]], ['decrease then partial restore', {'start': 1092, 'end': 1457, 'annual': 100000, 'endorsements': [[1105, 40005], [1285, 62765]]}, [-57858, 10725]], ['leap-year term', {'start': 820, 'end': 1186, 'annual': 204385, 'endorsements': [[905, 292674]]}, [67785]], ['six-month term', {'start': 1400, 'end': 1582, 'annual': 108639, 'endorsements': [[1481, 441832], [1570, 418671]]}, [184904, -1527]], ['endorsement on expiry rejected', {'start': 936, 'end': 1301, 'annual': 206524, 'endorsements': [[1301, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 983, 'end': 1348, 'annual': 294557, 'endorsements': [[982, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1953, 'end': 2318, 'annual': 262141, 'endorsements': [[2153, 200000], [2053, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2741, 'end': 3106, 'annual': 192566, 'endorsements': [[2741, 174344]]}, [-18222]], ['same-day endorsements', {'start': 114, 'end': 479, 'annual': 252584, 'endorsements': [[234, 250000], [234, 260000]]}, [-1734, 6712]], ['last day endorsement', {'start': 1695, 'end': 2060, 'annual': 100000, 'endorsements': [[2059, 111498]]}, [32]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    s=x['start']; e=x['end']; T=e-s
    def r(v): return math.floor(v+Fraction(1,2)) if v>=0 else -math.floor(-v+Fraction(1,2))
    cur=x['annual']; out=[]; last=s
    for d,new in x['endorsements']:
        if d<s or d>=e-1 or d<last: return 'invalid endorsement date'
        out.append(r(Fraction((new-cur)*(e-d),T)))
        cur=new; last=d
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['single increase', {'start': 2912, 'end': 3277, 'annual': 228520, 'endorsements': [[3043, 390228]]}, [103670]], ['increase then decrease', {'start': 477, 'end': 842, 'annual': 136883, 'endorsements': [[562, 340860], [681, 77377]]}, [156476, -116221]], ['decrease then partial restore', {'start': 2037, 'end': 2402, 'annual': 100000, 'endorsements': [[2109, 40001], [2277, 63890]]}, [-48164, 8181]], ['leap-year term', {'start': 2320, 'end': 2686, 'annual': 138690, 'endorsements': [[2497, 161560]]}, [11810]], ['six-month term', {'start': 2269, 'end': 2451, 'annual': 114166, 'endorsements': [[2418, 400299], [2439, 379739]]}, [51881, -1356]], ['endorsement on expiry rejected', {'start': 286, 'end': 651, 'annual': 174243, 'endorsements': [[651, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 962, 'end': 1327, 'annual': 166624, 'endorsements': [[961, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 251, 'end': 616, 'annual': 164047, 'endorsements': [[451, 200000], [351, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 579, 'end': 944, 'annual': 88017, 'endorsements': [[579, 316996]]}, [228979]], ['same-day endorsements', {'start': 17, 'end': 382, 'annual': 194026, 'endorsements': [[137, 250000], [137, 260000]]}, [37572, 6712]], ['last day endorsement', {'start': 2889, 'end': 3254, 'annual': 100000, 'endorsements': [[3253, 255567]]}, [426]]], [['single increase', {'start': 2490, 'end': 2855, 'annual': 104092, 'endorsements': [[2682, 358418]]}, [120544]], ['increase then decrease', {'start': 1761, 'end': 2126, 'annual': 95155, 'endorsements': [[1839, 390602], [1949, 60898]]}, [232310, -159884]], ['decrease then partial restore', {'start': 2809, 'end': 3174, 'annual': 100000, 'endorsements': [[2849, 40002], [3041, 65761]]}, [-53423, 9386]], ['leap-year term', {'start': 2789, 'end': 3155, 'annual': 136600, 'endorsements': [[3052, 310248]]}, [48868]], ['six-month term', {'start': 1197, 'end': 1379, 'annual': 163268, 'endorsements': [[1271, 255330], [1367, 168424]]}, [54630, -5730]], ['endorsement on expiry rejected', {'start': 48, 'end': 413, 'annual': 192511, 'endorsements': [[413, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1771, 'end': 2136, 'annual': 162702, 'endorsements': [[1770, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2865, 'end': 3230, 'annual': 261177, 'endorsements': [[3065, 200000], [2965, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 1467, 'end': 1832, 'annual': 116027, 'endorsements': [[1467, 190089]]}, [74062]], ['same-day endorsements', {'start': 847, 'end': 1212, 'annual': 109565, 'endorsements': [[967, 250000], [967, 260000]]}, [94265, 6712]], ['last day endorsement', {'start': 2776, 'end': 3141, 'annual': 100000, 'endorsements': [[3140, 396043]]}, [811]]], [['single increase', {'start': 1206, 'end': 1571, 'annual': 166000, 'endorsements': [[1276, 393494]]}, [183865]], ['increase then decrease', {'start': 749, 'end': 1114, 'annual': 280762, 'endorsements': [[848, 343990], [953, 67369]]}, [46078, -122016]], ['decrease then partial restore', {'start': 766, 'end': 1131, 'annual': 100000, 'endorsements': [[803, 40003], [1051, 69438]]}, [-53915, 6452]], ['leap-year term', {'start': 2028, 'end': 2394, 'annual': 148609, 'endorsements': [[2319, 100348]]}, [-9890]], ['six-month term', {'start': 1944, 'end': 2126, 'annual': 124458, 'endorsements': [[2010, 171861], [2114, 388840]]}, [30213, 14306]], ['endorsement on expiry rejected', {'start': 1174, 'end': 1539, 'annual': 115160, 'endorsements': [[1539, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 2665, 'end': 3030, 'annual': 152976, 'endorsements': [[2664, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1602, 'end': 1967, 'annual': 240101, 'endorsements': [[1802, 200000], [1702, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 908, 'end': 1273, 'annual': 148941, 'endorsements': [[908, 436896]]}, [287955]], ['same-day endorsements', {'start': 1319, 'end': 1684, 'annual': 113258, 'endorsements': [[1439, 250000], [1439, 260000]]}, [91786, 6712]], ['last day endorsement', {'start': 2821, 'end': 3186, 'annual': 100000, 'endorsements': [[3185, 367523]]}, [733]]], [['single increase', {'start': 2447, 'end': 2812, 'annual': 190688, 'endorsements': [[2655, 312597]]}, [52438]], ['increase then decrease', {'start': 1314, 'end': 1679, 'annual': 268062, 'endorsements': [[1335, 344123], [1518, 58352]]}, [71685, -126052]], ['decrease then partial restore', {'start': 1117, 'end': 1482, 'annual': 100000, 'endorsements': [[1159, 40004], [1334, 61238]]}, [-53092, 8610]], ['leap-year term', {'start': 1273, 'end': 1639, 'annual': 241312, 'endorsements': [[1536, 193555]]}, [-13440]], ['six-month term', {'start': 49, 'end': 231, 'annual': 80756, 'endorsements': [[79, 411368], [219, 276361]]}, [276116, -8902]], ['endorsement on expiry rejected', {'start': 2167, 'end': 2532, 'annual': 216523, 'endorsements': [[2532, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1680, 'end': 2045, 'annual': 258325, 'endorsements': [[1679, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2653, 'end': 3018, 'annual': 115795, 'endorsements': [[2853, 200000], [2753, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2438, 'end': 2803, 'annual': 251511, 'endorsements': [[2438, 112887]]}, [-138624]], ['same-day endorsements', {'start': 1751, 'end': 2116, 'annual': 210625, 'endorsements': [[1871, 250000], [1871, 260000]]}, [26430, 6712]], ['last day endorsement', {'start': 1049, 'end': 1414, 'annual': 100000, 'endorsements': [[1413, 290691]]}, [522]]], [['single increase', {'start': 567, 'end': 932, 'annual': 242069, 'endorsements': [[864, 340392]]}, [18318]], ['increase then decrease', {'start': 2519, 'end': 2884, 'annual': 179314, 'endorsements': [[2537, 319903], [2726, 81013]]}, [133656, -103410]], ['decrease then partial restore', {'start': 1092, 'end': 1457, 'annual': 100000, 'endorsements': [[1105, 40005], [1285, 62765]]}, [-57858, 10725]], ['leap-year term', {'start': 820, 'end': 1186, 'annual': 204385, 'endorsements': [[905, 292674]]}, [67785]], ['six-month term', {'start': 1400, 'end': 1582, 'annual': 108639, 'endorsements': [[1481, 441832], [1570, 418671]]}, [184904, -1527]], ['endorsement on expiry rejected', {'start': 936, 'end': 1301, 'annual': 206524, 'endorsements': [[1301, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 983, 'end': 1348, 'annual': 294557, 'endorsements': [[982, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1953, 'end': 2318, 'annual': 262141, 'endorsements': [[2153, 200000], [2053, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2741, 'end': 3106, 'annual': 192566, 'endorsements': [[2741, 174344]]}, [-18222]], ['same-day endorsements', {'start': 114, 'end': 479, 'annual': 252584, 'endorsements': [[234, 250000], [234, 260000]]}, [-1734, 6712]], ['last day endorsement', {'start': 1695, 'end': 2060, 'annual': 100000, 'endorsements': [[2059, 111498]]}, [32]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
An endorsement dated on the expiration date returns zero instead of an error.

Input start, end (days), annual premium, endorsements [[effective day, new annual premium]]. Dates must satisfy start<=d<end and be non-decreasing, else 'invalid endorsement date'. Each endorsement charges (new-current)*(end-d)/(end-start) rounded half away from zero, and the new premium becomes current.

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):
    s=x['start']; e=x['end']; T=e-s
    def r(v): return math.floor(v+Fraction(1,2)) if v>=0 else -math.floor(-v+Fraction(1,2))
    cur=x['annual']; out=[]; last=s
    for d,new in x['endorsements']:
        if d<s or d>=e or d<last: return 'invalid endorsement date'
        out.append(r(Fraction((new-cur)*(e-d),365)))
        cur=new; last=d
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['single increase', {'start': 2912, 'end': 3277, 'annual': 228520, 'endorsements': [[3043, 390228]]}, [103670]], ['increase then decrease', {'start': 477, 'end': 842, 'annual': 136883, 'endorsements': [[562, 340860], [681, 77377]]}, [156476, -116221]], ['decrease then partial restore', {'start': 2037, 'end': 2402, 'annual': 100000, 'endorsements': [[2109, 40001], [2277, 63890]]}, [-48164, 8181]], ['leap-year term', {'start': 2320, 'end': 2686, 'annual': 138690, 'endorsements': [[2497, 161560]]}, [11810]], ['six-month term', {'start': 2269, 'end': 2451, 'annual': 114166, 'endorsements': [[2418, 400299], [2439, 379739]]}, [51881, -1356]], ['endorsement on expiry rejected', {'start': 286, 'end': 651, 'annual': 174243, 'endorsements': [[651, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 962, 'end': 1327, 'annual': 166624, 'endorsements': [[961, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 251, 'end': 616, 'annual': 164047, 'endorsements': [[451, 200000], [351, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 579, 'end': 944, 'annual': 88017, 'endorsements': [[579, 316996]]}, [228979]], ['same-day endorsements', {'start': 17, 'end': 382, 'annual': 194026, 'endorsements': [[137, 250000], [137, 260000]]}, [37572, 6712]], ['last day endorsement', {'start': 2889, 'end': 3254, 'annual': 100000, 'endorsements': [[3253, 255567]]}, [426]]], [['single increase', {'start': 2490, 'end': 2855, 'annual': 104092, 'endorsements': [[2682, 358418]]}, [120544]], ['increase then decrease', {'start': 1761, 'end': 2126, 'annual': 95155, 'endorsements': [[1839, 390602], [1949, 60898]]}, [232310, -159884]], ['decrease then partial restore', {'start': 2809, 'end': 3174, 'annual': 100000, 'endorsements': [[2849, 40002], [3041, 65761]]}, [-53423, 9386]], ['leap-year term', {'start': 2789, 'end': 3155, 'annual': 136600, 'endorsements': [[3052, 310248]]}, [48868]], ['six-month term', {'start': 1197, 'end': 1379, 'annual': 163268, 'endorsements': [[1271, 255330], [1367, 168424]]}, [54630, -5730]], ['endorsement on expiry rejected', {'start': 48, 'end': 413, 'annual': 192511, 'endorsements': [[413, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1771, 'end': 2136, 'annual': 162702, 'endorsements': [[1770, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2865, 'end': 3230, 'annual': 261177, 'endorsements': [[3065, 200000], [2965, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 1467, 'end': 1832, 'annual': 116027, 'endorsements': [[1467, 190089]]}, [74062]], ['same-day endorsements', {'start': 847, 'end': 1212, 'annual': 109565, 'endorsements': [[967, 250000], [967, 260000]]}, [94265, 6712]], ['last day endorsement', {'start': 2776, 'end': 3141, 'annual': 100000, 'endorsements': [[3140, 396043]]}, [811]]], [['single increase', {'start': 1206, 'end': 1571, 'annual': 166000, 'endorsements': [[1276, 393494]]}, [183865]], ['increase then decrease', {'start': 749, 'end': 1114, 'annual': 280762, 'endorsements': [[848, 343990], [953, 67369]]}, [46078, -122016]], ['decrease then partial restore', {'start': 766, 'end': 1131, 'annual': 100000, 'endorsements': [[803, 40003], [1051, 69438]]}, [-53915, 6452]], ['leap-year term', {'start': 2028, 'end': 2394, 'annual': 148609, 'endorsements': [[2319, 100348]]}, [-9890]], ['six-month term', {'start': 1944, 'end': 2126, 'annual': 124458, 'endorsements': [[2010, 171861], [2114, 388840]]}, [30213, 14306]], ['endorsement on expiry rejected', {'start': 1174, 'end': 1539, 'annual': 115160, 'endorsements': [[1539, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 2665, 'end': 3030, 'annual': 152976, 'endorsements': [[2664, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1602, 'end': 1967, 'annual': 240101, 'endorsements': [[1802, 200000], [1702, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 908, 'end': 1273, 'annual': 148941, 'endorsements': [[908, 436896]]}, [287955]], ['same-day endorsements', {'start': 1319, 'end': 1684, 'annual': 113258, 'endorsements': [[1439, 250000], [1439, 260000]]}, [91786, 6712]], ['last day endorsement', {'start': 2821, 'end': 3186, 'annual': 100000, 'endorsements': [[3185, 367523]]}, [733]]], [['single increase', {'start': 2447, 'end': 2812, 'annual': 190688, 'endorsements': [[2655, 312597]]}, [52438]], ['increase then decrease', {'start': 1314, 'end': 1679, 'annual': 268062, 'endorsements': [[1335, 344123], [1518, 58352]]}, [71685, -126052]], ['decrease then partial restore', {'start': 1117, 'end': 1482, 'annual': 100000, 'endorsements': [[1159, 40004], [1334, 61238]]}, [-53092, 8610]], ['leap-year term', {'start': 1273, 'end': 1639, 'annual': 241312, 'endorsements': [[1536, 193555]]}, [-13440]], ['six-month term', {'start': 49, 'end': 231, 'annual': 80756, 'endorsements': [[79, 411368], [219, 276361]]}, [276116, -8902]], ['endorsement on expiry rejected', {'start': 2167, 'end': 2532, 'annual': 216523, 'endorsements': [[2532, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1680, 'end': 2045, 'annual': 258325, 'endorsements': [[1679, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2653, 'end': 3018, 'annual': 115795, 'endorsements': [[2853, 200000], [2753, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2438, 'end': 2803, 'annual': 251511, 'endorsements': [[2438, 112887]]}, [-138624]], ['same-day endorsements', {'start': 1751, 'end': 2116, 'annual': 210625, 'endorsements': [[1871, 250000], [1871, 260000]]}, [26430, 6712]], ['last day endorsement', {'start': 1049, 'end': 1414, 'annual': 100000, 'endorsements': [[1413, 290691]]}, [522]]], [['single increase', {'start': 567, 'end': 932, 'annual': 242069, 'endorsements': [[864, 340392]]}, [18318]], ['increase then decrease', {'start': 2519, 'end': 2884, 'annual': 179314, 'endorsements': [[2537, 319903], [2726, 81013]]}, [133656, -103410]], ['decrease then partial restore', {'start': 1092, 'end': 1457, 'annual': 100000, 'endorsements': [[1105, 40005], [1285, 62765]]}, [-57858, 10725]], ['leap-year term', {'start': 820, 'end': 1186, 'annual': 204385, 'endorsements': [[905, 292674]]}, [67785]], ['six-month term', {'start': 1400, 'end': 1582, 'annual': 108639, 'endorsements': [[1481, 441832], [1570, 418671]]}, [184904, -1527]], ['endorsement on expiry rejected', {'start': 936, 'end': 1301, 'annual': 206524, 'endorsements': [[1301, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 983, 'end': 1348, 'annual': 294557, 'endorsements': [[982, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1953, 'end': 2318, 'annual': 262141, 'endorsements': [[2153, 200000], [2053, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2741, 'end': 3106, 'annual': 192566, 'endorsements': [[2741, 174344]]}, [-18222]], ['same-day endorsements', {'start': 114, 'end': 479, 'annual': 252584, 'endorsements': [[234, 250000], [234, 260000]]}, [-1734, 6712]], ['last day endorsement', {'start': 1695, 'end': 2060, 'annual': 100000, 'endorsements': [[2059, 111498]]}, [32]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    s=x['start']; e=x['end']; T=e-s
    def r(v): return math.floor(v+Fraction(1,2)) if v>=0 else -math.floor(-v+Fraction(1,2))
    cur=x['annual']; out=[]; last=s
    for d,new in x['endorsements']:
        if d<s or d>=e or d<last: return 'invalid endorsement date'
        out.append(r(Fraction((new-cur)*(e-d),T+1)))
        cur=new; last=d
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['single increase', {'start': 2912, 'end': 3277, 'annual': 228520, 'endorsements': [[3043, 390228]]}, [103670]], ['increase then decrease', {'start': 477, 'end': 842, 'annual': 136883, 'endorsements': [[562, 340860], [681, 77377]]}, [156476, -116221]], ['decrease then partial restore', {'start': 2037, 'end': 2402, 'annual': 100000, 'endorsements': [[2109, 40001], [2277, 63890]]}, [-48164, 8181]], ['leap-year term', {'start': 2320, 'end': 2686, 'annual': 138690, 'endorsements': [[2497, 161560]]}, [11810]], ['six-month term', {'start': 2269, 'end': 2451, 'annual': 114166, 'endorsements': [[2418, 400299], [2439, 379739]]}, [51881, -1356]], ['endorsement on expiry rejected', {'start': 286, 'end': 651, 'annual': 174243, 'endorsements': [[651, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 962, 'end': 1327, 'annual': 166624, 'endorsements': [[961, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 251, 'end': 616, 'annual': 164047, 'endorsements': [[451, 200000], [351, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 579, 'end': 944, 'annual': 88017, 'endorsements': [[579, 316996]]}, [228979]], ['same-day endorsements', {'start': 17, 'end': 382, 'annual': 194026, 'endorsements': [[137, 250000], [137, 260000]]}, [37572, 6712]], ['last day endorsement', {'start': 2889, 'end': 3254, 'annual': 100000, 'endorsements': [[3253, 255567]]}, [426]]], [['single increase', {'start': 2490, 'end': 2855, 'annual': 104092, 'endorsements': [[2682, 358418]]}, [120544]], ['increase then decrease', {'start': 1761, 'end': 2126, 'annual': 95155, 'endorsements': [[1839, 390602], [1949, 60898]]}, [232310, -159884]], ['decrease then partial restore', {'start': 2809, 'end': 3174, 'annual': 100000, 'endorsements': [[2849, 40002], [3041, 65761]]}, [-53423, 9386]], ['leap-year term', {'start': 2789, 'end': 3155, 'annual': 136600, 'endorsements': [[3052, 310248]]}, [48868]], ['six-month term', {'start': 1197, 'end': 1379, 'annual': 163268, 'endorsements': [[1271, 255330], [1367, 168424]]}, [54630, -5730]], ['endorsement on expiry rejected', {'start': 48, 'end': 413, 'annual': 192511, 'endorsements': [[413, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1771, 'end': 2136, 'annual': 162702, 'endorsements': [[1770, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2865, 'end': 3230, 'annual': 261177, 'endorsements': [[3065, 200000], [2965, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 1467, 'end': 1832, 'annual': 116027, 'endorsements': [[1467, 190089]]}, [74062]], ['same-day endorsements', {'start': 847, 'end': 1212, 'annual': 109565, 'endorsements': [[967, 250000], [967, 260000]]}, [94265, 6712]], ['last day endorsement', {'start': 2776, 'end': 3141, 'annual': 100000, 'endorsements': [[3140, 396043]]}, [811]]], [['single increase', {'start': 1206, 'end': 1571, 'annual': 166000, 'endorsements': [[1276, 393494]]}, [183865]], ['increase then decrease', {'start': 749, 'end': 1114, 'annual': 280762, 'endorsements': [[848, 343990], [953, 67369]]}, [46078, -122016]], ['decrease then partial restore', {'start': 766, 'end': 1131, 'annual': 100000, 'endorsements': [[803, 40003], [1051, 69438]]}, [-53915, 6452]], ['leap-year term', {'start': 2028, 'end': 2394, 'annual': 148609, 'endorsements': [[2319, 100348]]}, [-9890]], ['six-month term', {'start': 1944, 'end': 2126, 'annual': 124458, 'endorsements': [[2010, 171861], [2114, 388840]]}, [30213, 14306]], ['endorsement on expiry rejected', {'start': 1174, 'end': 1539, 'annual': 115160, 'endorsements': [[1539, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 2665, 'end': 3030, 'annual': 152976, 'endorsements': [[2664, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1602, 'end': 1967, 'annual': 240101, 'endorsements': [[1802, 200000], [1702, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 908, 'end': 1273, 'annual': 148941, 'endorsements': [[908, 436896]]}, [287955]], ['same-day endorsements', {'start': 1319, 'end': 1684, 'annual': 113258, 'endorsements': [[1439, 250000], [1439, 260000]]}, [91786, 6712]], ['last day endorsement', {'start': 2821, 'end': 3186, 'annual': 100000, 'endorsements': [[3185, 367523]]}, [733]]], [['single increase', {'start': 2447, 'end': 2812, 'annual': 190688, 'endorsements': [[2655, 312597]]}, [52438]], ['increase then decrease', {'start': 1314, 'end': 1679, 'annual': 268062, 'endorsements': [[1335, 344123], [1518, 58352]]}, [71685, -126052]], ['decrease then partial restore', {'start': 1117, 'end': 1482, 'annual': 100000, 'endorsements': [[1159, 40004], [1334, 61238]]}, [-53092, 8610]], ['leap-year term', {'start': 1273, 'end': 1639, 'annual': 241312, 'endorsements': [[1536, 193555]]}, [-13440]], ['six-month term', {'start': 49, 'end': 231, 'annual': 80756, 'endorsements': [[79, 411368], [219, 276361]]}, [276116, -8902]], ['endorsement on expiry rejected', {'start': 2167, 'end': 2532, 'annual': 216523, 'endorsements': [[2532, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1680, 'end': 2045, 'annual': 258325, 'endorsements': [[1679, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2653, 'end': 3018, 'annual': 115795, 'endorsements': [[2853, 200000], [2753, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2438, 'end': 2803, 'annual': 251511, 'endorsements': [[2438, 112887]]}, [-138624]], ['same-day endorsements', {'start': 1751, 'end': 2116, 'annual': 210625, 'endorsements': [[1871, 250000], [1871, 260000]]}, [26430, 6712]], ['last day endorsement', {'start': 1049, 'end': 1414, 'annual': 100000, 'endorsements': [[1413, 290691]]}, [522]]], [['single increase', {'start': 567, 'end': 932, 'annual': 242069, 'endorsements': [[864, 340392]]}, [18318]], ['increase then decrease', {'start': 2519, 'end': 2884, 'annual': 179314, 'endorsements': [[2537, 319903], [2726, 81013]]}, [133656, -103410]], ['decrease then partial restore', {'start': 1092, 'end': 1457, 'annual': 100000, 'endorsements': [[1105, 40005], [1285, 62765]]}, [-57858, 10725]], ['leap-year term', {'start': 820, 'end': 1186, 'annual': 204385, 'endorsements': [[905, 292674]]}, [67785]], ['six-month term', {'start': 1400, 'end': 1582, 'annual': 108639, 'endorsements': [[1481, 441832], [1570, 418671]]}, [184904, -1527]], ['endorsement on expiry rejected', {'start': 936, 'end': 1301, 'annual': 206524, 'endorsements': [[1301, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 983, 'end': 1348, 'annual': 294557, 'endorsements': [[982, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1953, 'end': 2318, 'annual': 262141, 'endorsements': [[2153, 200000], [2053, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2741, 'end': 3106, 'annual': 192566, 'endorsements': [[2741, 174344]]}, [-18222]], ['same-day endorsements', {'start': 114, 'end': 479, 'annual': 252584, 'endorsements': [[234, 250000], [234, 260000]]}, [-1734, 6712]], ['last day endorsement', {'start': 1695, 'end': 2060, 'annual': 100000, 'endorsements': [[2059, 111498]]}, [32]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Short-term and leap-year policies are prorated on the wrong base.

Input start, end (days), annual premium, endorsements [[effective day, new annual premium]]. Dates must satisfy start<=d<end and be non-decreasing, else 'invalid endorsement date'. Each endorsement charges (new-current)*(end-d)/(end-start) rounded half away from zero, and the new premium becomes current.

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):
    s=x['start']; e=x['end']; T=e-s
    def r(v): return math.floor(v+Fraction(1,2)) if v>=0 else -math.floor(-v+Fraction(1,2))
    cur=x['annual']; out=[]; last=s
    for d,new in x['endorsements']:
        if d<s or d>=e: return 'invalid endorsement date'
        out.append(r(Fraction((new-cur)*(e-d),T)))
        cur=new; last=d
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['single increase', {'start': 2912, 'end': 3277, 'annual': 228520, 'endorsements': [[3043, 390228]]}, [103670]], ['increase then decrease', {'start': 477, 'end': 842, 'annual': 136883, 'endorsements': [[562, 340860], [681, 77377]]}, [156476, -116221]], ['decrease then partial restore', {'start': 2037, 'end': 2402, 'annual': 100000, 'endorsements': [[2109, 40001], [2277, 63890]]}, [-48164, 8181]], ['leap-year term', {'start': 2320, 'end': 2686, 'annual': 138690, 'endorsements': [[2497, 161560]]}, [11810]], ['six-month term', {'start': 2269, 'end': 2451, 'annual': 114166, 'endorsements': [[2418, 400299], [2439, 379739]]}, [51881, -1356]], ['endorsement on expiry rejected', {'start': 286, 'end': 651, 'annual': 174243, 'endorsements': [[651, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 962, 'end': 1327, 'annual': 166624, 'endorsements': [[961, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 251, 'end': 616, 'annual': 164047, 'endorsements': [[451, 200000], [351, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 579, 'end': 944, 'annual': 88017, 'endorsements': [[579, 316996]]}, [228979]], ['same-day endorsements', {'start': 17, 'end': 382, 'annual': 194026, 'endorsements': [[137, 250000], [137, 260000]]}, [37572, 6712]], ['last day endorsement', {'start': 2889, 'end': 3254, 'annual': 100000, 'endorsements': [[3253, 255567]]}, [426]]], [['single increase', {'start': 2490, 'end': 2855, 'annual': 104092, 'endorsements': [[2682, 358418]]}, [120544]], ['increase then decrease', {'start': 1761, 'end': 2126, 'annual': 95155, 'endorsements': [[1839, 390602], [1949, 60898]]}, [232310, -159884]], ['decrease then partial restore', {'start': 2809, 'end': 3174, 'annual': 100000, 'endorsements': [[2849, 40002], [3041, 65761]]}, [-53423, 9386]], ['leap-year term', {'start': 2789, 'end': 3155, 'annual': 136600, 'endorsements': [[3052, 310248]]}, [48868]], ['six-month term', {'start': 1197, 'end': 1379, 'annual': 163268, 'endorsements': [[1271, 255330], [1367, 168424]]}, [54630, -5730]], ['endorsement on expiry rejected', {'start': 48, 'end': 413, 'annual': 192511, 'endorsements': [[413, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1771, 'end': 2136, 'annual': 162702, 'endorsements': [[1770, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2865, 'end': 3230, 'annual': 261177, 'endorsements': [[3065, 200000], [2965, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 1467, 'end': 1832, 'annual': 116027, 'endorsements': [[1467, 190089]]}, [74062]], ['same-day endorsements', {'start': 847, 'end': 1212, 'annual': 109565, 'endorsements': [[967, 250000], [967, 260000]]}, [94265, 6712]], ['last day endorsement', {'start': 2776, 'end': 3141, 'annual': 100000, 'endorsements': [[3140, 396043]]}, [811]]], [['single increase', {'start': 1206, 'end': 1571, 'annual': 166000, 'endorsements': [[1276, 393494]]}, [183865]], ['increase then decrease', {'start': 749, 'end': 1114, 'annual': 280762, 'endorsements': [[848, 343990], [953, 67369]]}, [46078, -122016]], ['decrease then partial restore', {'start': 766, 'end': 1131, 'annual': 100000, 'endorsements': [[803, 40003], [1051, 69438]]}, [-53915, 6452]], ['leap-year term', {'start': 2028, 'end': 2394, 'annual': 148609, 'endorsements': [[2319, 100348]]}, [-9890]], ['six-month term', {'start': 1944, 'end': 2126, 'annual': 124458, 'endorsements': [[2010, 171861], [2114, 388840]]}, [30213, 14306]], ['endorsement on expiry rejected', {'start': 1174, 'end': 1539, 'annual': 115160, 'endorsements': [[1539, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 2665, 'end': 3030, 'annual': 152976, 'endorsements': [[2664, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1602, 'end': 1967, 'annual': 240101, 'endorsements': [[1802, 200000], [1702, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 908, 'end': 1273, 'annual': 148941, 'endorsements': [[908, 436896]]}, [287955]], ['same-day endorsements', {'start': 1319, 'end': 1684, 'annual': 113258, 'endorsements': [[1439, 250000], [1439, 260000]]}, [91786, 6712]], ['last day endorsement', {'start': 2821, 'end': 3186, 'annual': 100000, 'endorsements': [[3185, 367523]]}, [733]]], [['single increase', {'start': 2447, 'end': 2812, 'annual': 190688, 'endorsements': [[2655, 312597]]}, [52438]], ['increase then decrease', {'start': 1314, 'end': 1679, 'annual': 268062, 'endorsements': [[1335, 344123], [1518, 58352]]}, [71685, -126052]], ['decrease then partial restore', {'start': 1117, 'end': 1482, 'annual': 100000, 'endorsements': [[1159, 40004], [1334, 61238]]}, [-53092, 8610]], ['leap-year term', {'start': 1273, 'end': 1639, 'annual': 241312, 'endorsements': [[1536, 193555]]}, [-13440]], ['six-month term', {'start': 49, 'end': 231, 'annual': 80756, 'endorsements': [[79, 411368], [219, 276361]]}, [276116, -8902]], ['endorsement on expiry rejected', {'start': 2167, 'end': 2532, 'annual': 216523, 'endorsements': [[2532, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1680, 'end': 2045, 'annual': 258325, 'endorsements': [[1679, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2653, 'end': 3018, 'annual': 115795, 'endorsements': [[2853, 200000], [2753, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2438, 'end': 2803, 'annual': 251511, 'endorsements': [[2438, 112887]]}, [-138624]], ['same-day endorsements', {'start': 1751, 'end': 2116, 'annual': 210625, 'endorsements': [[1871, 250000], [1871, 260000]]}, [26430, 6712]], ['last day endorsement', {'start': 1049, 'end': 1414, 'annual': 100000, 'endorsements': [[1413, 290691]]}, [522]]], [['single increase', {'start': 567, 'end': 932, 'annual': 242069, 'endorsements': [[864, 340392]]}, [18318]], ['increase then decrease', {'start': 2519, 'end': 2884, 'annual': 179314, 'endorsements': [[2537, 319903], [2726, 81013]]}, [133656, -103410]], ['decrease then partial restore', {'start': 1092, 'end': 1457, 'annual': 100000, 'endorsements': [[1105, 40005], [1285, 62765]]}, [-57858, 10725]], ['leap-year term', {'start': 820, 'end': 1186, 'annual': 204385, 'endorsements': [[905, 292674]]}, [67785]], ['six-month term', {'start': 1400, 'end': 1582, 'annual': 108639, 'endorsements': [[1481, 441832], [1570, 418671]]}, [184904, -1527]], ['endorsement on expiry rejected', {'start': 936, 'end': 1301, 'annual': 206524, 'endorsements': [[1301, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 983, 'end': 1348, 'annual': 294557, 'endorsements': [[982, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1953, 'end': 2318, 'annual': 262141, 'endorsements': [[2153, 200000], [2053, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2741, 'end': 3106, 'annual': 192566, 'endorsements': [[2741, 174344]]}, [-18222]], ['same-day endorsements', {'start': 114, 'end': 479, 'annual': 252584, 'endorsements': [[234, 250000], [234, 260000]]}, [-1734, 6712]], ['last day endorsement', {'start': 1695, 'end': 2060, 'annual': 100000, 'endorsements': [[2059, 111498]]}, [32]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    s=x['start']; e=x['end']; T=e-s
    def r(v): return math.floor(v+Fraction(1,2)) if v>=0 else -math.floor(-v+Fraction(1,2))
    cur=x['annual']; out=[]; last=s
    for d,new in x['endorsements']:
        if d<s or d>=e or d<=last: return 'invalid endorsement date'
        out.append(r(Fraction((new-cur)*(e-d),T)))
        cur=new; last=d
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['single increase', {'start': 2912, 'end': 3277, 'annual': 228520, 'endorsements': [[3043, 390228]]}, [103670]], ['increase then decrease', {'start': 477, 'end': 842, 'annual': 136883, 'endorsements': [[562, 340860], [681, 77377]]}, [156476, -116221]], ['decrease then partial restore', {'start': 2037, 'end': 2402, 'annual': 100000, 'endorsements': [[2109, 40001], [2277, 63890]]}, [-48164, 8181]], ['leap-year term', {'start': 2320, 'end': 2686, 'annual': 138690, 'endorsements': [[2497, 161560]]}, [11810]], ['six-month term', {'start': 2269, 'end': 2451, 'annual': 114166, 'endorsements': [[2418, 400299], [2439, 379739]]}, [51881, -1356]], ['endorsement on expiry rejected', {'start': 286, 'end': 651, 'annual': 174243, 'endorsements': [[651, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 962, 'end': 1327, 'annual': 166624, 'endorsements': [[961, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 251, 'end': 616, 'annual': 164047, 'endorsements': [[451, 200000], [351, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 579, 'end': 944, 'annual': 88017, 'endorsements': [[579, 316996]]}, [228979]], ['same-day endorsements', {'start': 17, 'end': 382, 'annual': 194026, 'endorsements': [[137, 250000], [137, 260000]]}, [37572, 6712]], ['last day endorsement', {'start': 2889, 'end': 3254, 'annual': 100000, 'endorsements': [[3253, 255567]]}, [426]]], [['single increase', {'start': 2490, 'end': 2855, 'annual': 104092, 'endorsements': [[2682, 358418]]}, [120544]], ['increase then decrease', {'start': 1761, 'end': 2126, 'annual': 95155, 'endorsements': [[1839, 390602], [1949, 60898]]}, [232310, -159884]], ['decrease then partial restore', {'start': 2809, 'end': 3174, 'annual': 100000, 'endorsements': [[2849, 40002], [3041, 65761]]}, [-53423, 9386]], ['leap-year term', {'start': 2789, 'end': 3155, 'annual': 136600, 'endorsements': [[3052, 310248]]}, [48868]], ['six-month term', {'start': 1197, 'end': 1379, 'annual': 163268, 'endorsements': [[1271, 255330], [1367, 168424]]}, [54630, -5730]], ['endorsement on expiry rejected', {'start': 48, 'end': 413, 'annual': 192511, 'endorsements': [[413, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1771, 'end': 2136, 'annual': 162702, 'endorsements': [[1770, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2865, 'end': 3230, 'annual': 261177, 'endorsements': [[3065, 200000], [2965, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 1467, 'end': 1832, 'annual': 116027, 'endorsements': [[1467, 190089]]}, [74062]], ['same-day endorsements', {'start': 847, 'end': 1212, 'annual': 109565, 'endorsements': [[967, 250000], [967, 260000]]}, [94265, 6712]], ['last day endorsement', {'start': 2776, 'end': 3141, 'annual': 100000, 'endorsements': [[3140, 396043]]}, [811]]], [['single increase', {'start': 1206, 'end': 1571, 'annual': 166000, 'endorsements': [[1276, 393494]]}, [183865]], ['increase then decrease', {'start': 749, 'end': 1114, 'annual': 280762, 'endorsements': [[848, 343990], [953, 67369]]}, [46078, -122016]], ['decrease then partial restore', {'start': 766, 'end': 1131, 'annual': 100000, 'endorsements': [[803, 40003], [1051, 69438]]}, [-53915, 6452]], ['leap-year term', {'start': 2028, 'end': 2394, 'annual': 148609, 'endorsements': [[2319, 100348]]}, [-9890]], ['six-month term', {'start': 1944, 'end': 2126, 'annual': 124458, 'endorsements': [[2010, 171861], [2114, 388840]]}, [30213, 14306]], ['endorsement on expiry rejected', {'start': 1174, 'end': 1539, 'annual': 115160, 'endorsements': [[1539, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 2665, 'end': 3030, 'annual': 152976, 'endorsements': [[2664, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1602, 'end': 1967, 'annual': 240101, 'endorsements': [[1802, 200000], [1702, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 908, 'end': 1273, 'annual': 148941, 'endorsements': [[908, 436896]]}, [287955]], ['same-day endorsements', {'start': 1319, 'end': 1684, 'annual': 113258, 'endorsements': [[1439, 250000], [1439, 260000]]}, [91786, 6712]], ['last day endorsement', {'start': 2821, 'end': 3186, 'annual': 100000, 'endorsements': [[3185, 367523]]}, [733]]], [['single increase', {'start': 2447, 'end': 2812, 'annual': 190688, 'endorsements': [[2655, 312597]]}, [52438]], ['increase then decrease', {'start': 1314, 'end': 1679, 'annual': 268062, 'endorsements': [[1335, 344123], [1518, 58352]]}, [71685, -126052]], ['decrease then partial restore', {'start': 1117, 'end': 1482, 'annual': 100000, 'endorsements': [[1159, 40004], [1334, 61238]]}, [-53092, 8610]], ['leap-year term', {'start': 1273, 'end': 1639, 'annual': 241312, 'endorsements': [[1536, 193555]]}, [-13440]], ['six-month term', {'start': 49, 'end': 231, 'annual': 80756, 'endorsements': [[79, 411368], [219, 276361]]}, [276116, -8902]], ['endorsement on expiry rejected', {'start': 2167, 'end': 2532, 'annual': 216523, 'endorsements': [[2532, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 1680, 'end': 2045, 'annual': 258325, 'endorsements': [[1679, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 2653, 'end': 3018, 'annual': 115795, 'endorsements': [[2853, 200000], [2753, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2438, 'end': 2803, 'annual': 251511, 'endorsements': [[2438, 112887]]}, [-138624]], ['same-day endorsements', {'start': 1751, 'end': 2116, 'annual': 210625, 'endorsements': [[1871, 250000], [1871, 260000]]}, [26430, 6712]], ['last day endorsement', {'start': 1049, 'end': 1414, 'annual': 100000, 'endorsements': [[1413, 290691]]}, [522]]], [['single increase', {'start': 567, 'end': 932, 'annual': 242069, 'endorsements': [[864, 340392]]}, [18318]], ['increase then decrease', {'start': 2519, 'end': 2884, 'annual': 179314, 'endorsements': [[2537, 319903], [2726, 81013]]}, [133656, -103410]], ['decrease then partial restore', {'start': 1092, 'end': 1457, 'annual': 100000, 'endorsements': [[1105, 40005], [1285, 62765]]}, [-57858, 10725]], ['leap-year term', {'start': 820, 'end': 1186, 'annual': 204385, 'endorsements': [[905, 292674]]}, [67785]], ['six-month term', {'start': 1400, 'end': 1582, 'annual': 108639, 'endorsements': [[1481, 441832], [1570, 418671]]}, [184904, -1527]], ['endorsement on expiry rejected', {'start': 936, 'end': 1301, 'annual': 206524, 'endorsements': [[1301, 200000]]}, 'invalid endorsement date'], ['endorsement before inception rejected', {'start': 983, 'end': 1348, 'annual': 294557, 'endorsements': [[982, 200000]]}, 'invalid endorsement date'], ['out of order rejected', {'start': 1953, 'end': 2318, 'annual': 262141, 'endorsements': [[2153, 200000], [2053, 250000]]}, 'invalid endorsement date'], ['inception-day endorsement', {'start': 2741, 'end': 3106, 'annual': 192566, 'endorsements': [[2741, 174344]]}, [-18222]], ['same-day endorsements', {'start': 114, 'end': 479, 'annual': 252584, 'endorsements': [[234, 250000], [234, 260000]]}, [-1734, 6712]], ['last day endorsement', {'start': 1695, 'end': 2060, 'annual': 100000, 'endorsements': [[2059, 111498]]}, [32]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Backdated endorsements are processed in the wrong order.

Input start, end (days), annual premium, endorsements [[effective day, new annual premium]]. Dates must satisfy start<=d<end and be non-decreasing, else 'invalid endorsement date'. Each endorsement charges (new-current)*(end-d)/(end-start) rounded half away from zero, and the new premium becomes current.

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):
    prev=x['prior']; out=[]
    for ind,changed in x['years']:
        if ind is None:
            out.append(None); prev=0; continue
        if changed or prev==0:
            cur=ind
        else:
            hi=math.floor(Fraction(prev*(1000+x['up']),1000)+Fraction(1,2))
            lo=math.floor(Fraction(prev*(1000-x['down']),1000)+Fraction(1,2))
            cur=max(lo,min(hi,ind))
        out.append(cur); prev=ind
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['large increase phased in', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, False], [282332, False], [282332, False]]}, [156694, 173930, 193062]], ['large decrease capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[70583, False], [70583, False]]}, [134108, 127403]], ['coverage change exempt then capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, True], [423498, False]]}, [282332, 313389]], ['new business exempt', {'prior': 0, 'up': 110, 'down': 50, 'years': [[141166, False], [282332, False]]}, [141166, 156694]], ['lapse restarts as new business', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[141166, False], [None, False], [423498, False]]}, [141166, None, 423498]], ['within caps', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[142166, False], [140166, False]]}, [142166, 140166]], ['mixed history', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[172018, False], [166564, False], [197332, False], [213340, False]]}, [156694, 166564, 184886, 205223]]], [['large increase phased in', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, False], [163834, False], [163834, False]]}, [91747, 102757, 115088]], ['large decrease capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[40958, False], [40958, False]]}, [77821, 73930]], ['coverage change exempt then capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, True], [245751, False]]}, [163834, 183494]], ['new business exempt', {'prior': 0, 'up': 120, 'down': 50, 'years': [[81917, False], [163834, False]]}, [81917, 91747]], ['lapse restarts as new business', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[81917, False], [None, False], [245751, False]]}, [81917, None, 245751]], ['within caps', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[82917, False], [80917, False]]}, [82917, 80917]], ['mixed history', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[92584, False], [202024, False], [62931, True], [150823, False]]}, [91747, 102757, 62931, 70483]]], [['large increase phased in', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, False], [280726, False], [280726, False]]}, [158610, 179229, 202529]], ['large decrease capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[70181, False], [70181, False]]}, [133345, 126678]], ['coverage change exempt then capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, True], [421089, False]]}, [280726, 317220]], ['new business exempt', {'prior': 0, 'up': 130, 'down': 50, 'years': [[140363, False], [280726, False]]}, [140363, 158610]], ['lapse restarts as new business', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[140363, False], [None, False], [421089, False]]}, [140363, None, 421089]], ['within caps', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[141363, False], [139363, False]]}, [141363, 139363]], ['mixed history', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[224001, True], [54488, False], [53043, False], [82834, False]]}, [224001, 212801, 202161, 192053]]], [['large increase phased in', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, False], [262850, False], [262850, False]]}, [149825, 170801, 194713]], ['large decrease capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[65712, False], [65712, False]]}, [124854, 118611]], ['coverage change exempt then capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, True], [394275, False]]}, [262850, 299649]], ['new business exempt', {'prior': 0, 'up': 140, 'down': 50, 'years': [[131425, False], [262850, False]]}, [131425, 149825]], ['lapse restarts as new business', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[131425, False], [None, False], [394275, False]]}, [131425, None, 394275]], ['within caps', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[132425, False], [130425, False]]}, [132425, 130425]], ['mixed history', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[105255, True], [201448, True], [175992, True], [84220, False]]}, [105255, 201448, 175992, 167192]]], [['large increase phased in', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, False], [258006, False], [258006, False]]}, [148353, 170606, 196197]], ['large decrease capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[64501, False], [64501, False]]}, [122553, 116425]], ['coverage change exempt then capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, True], [387009, False]]}, [258006, 296707]], ['new business exempt', {'prior': 0, 'up': 150, 'down': 50, 'years': [[129003, False], [258006, False]]}, [129003, 148353]], ['lapse restarts as new business', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[129003, False], [None, False], [387009, False]]}, [129003, None, 387009]], ['within caps', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[130003, False], [128003, False]]}, [130003, 128003]], ['mixed history', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[151965, False], [114334, False], [235286, False], [180318, True]]}, [148353, 140935, 162075, 180318]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    prev=x['prior']; out=[]
    for ind,changed in x['years']:
        if ind is None:
            out.append(None); prev=0; continue
        if changed or prev==0:
            cur=ind
        else:
            hi=math.floor(Fraction(prev*(1000+x['up']),1000)+Fraction(1,2))
            lo=math.floor(Fraction(prev*(1000-x['down']),1000)+Fraction(1,2))
            cur=max(lo,min(hi,ind))
        out.append(cur); prev=cur if changed else ind
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['large increase phased in', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, False], [282332, False], [282332, False]]}, [156694, 173930, 193062]], ['large decrease capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[70583, False], [70583, False]]}, [134108, 127403]], ['coverage change exempt then capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, True], [423498, False]]}, [282332, 313389]], ['new business exempt', {'prior': 0, 'up': 110, 'down': 50, 'years': [[141166, False], [282332, False]]}, [141166, 156694]], ['lapse restarts as new business', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[141166, False], [None, False], [423498, False]]}, [141166, None, 423498]], ['within caps', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[142166, False], [140166, False]]}, [142166, 140166]], ['mixed history', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[172018, False], [166564, False], [197332, False], [213340, False]]}, [156694, 166564, 184886, 205223]]], [['large increase phased in', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, False], [163834, False], [163834, False]]}, [91747, 102757, 115088]], ['large decrease capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[40958, False], [40958, False]]}, [77821, 73930]], ['coverage change exempt then capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, True], [245751, False]]}, [163834, 183494]], ['new business exempt', {'prior': 0, 'up': 120, 'down': 50, 'years': [[81917, False], [163834, False]]}, [81917, 91747]], ['lapse restarts as new business', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[81917, False], [None, False], [245751, False]]}, [81917, None, 245751]], ['within caps', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[82917, False], [80917, False]]}, [82917, 80917]], ['mixed history', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[92584, False], [202024, False], [62931, True], [150823, False]]}, [91747, 102757, 62931, 70483]]], [['large increase phased in', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, False], [280726, False], [280726, False]]}, [158610, 179229, 202529]], ['large decrease capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[70181, False], [70181, False]]}, [133345, 126678]], ['coverage change exempt then capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, True], [421089, False]]}, [280726, 317220]], ['new business exempt', {'prior': 0, 'up': 130, 'down': 50, 'years': [[140363, False], [280726, False]]}, [140363, 158610]], ['lapse restarts as new business', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[140363, False], [None, False], [421089, False]]}, [140363, None, 421089]], ['within caps', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[141363, False], [139363, False]]}, [141363, 139363]], ['mixed history', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[224001, True], [54488, False], [53043, False], [82834, False]]}, [224001, 212801, 202161, 192053]]], [['large increase phased in', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, False], [262850, False], [262850, False]]}, [149825, 170801, 194713]], ['large decrease capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[65712, False], [65712, False]]}, [124854, 118611]], ['coverage change exempt then capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, True], [394275, False]]}, [262850, 299649]], ['new business exempt', {'prior': 0, 'up': 140, 'down': 50, 'years': [[131425, False], [262850, False]]}, [131425, 149825]], ['lapse restarts as new business', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[131425, False], [None, False], [394275, False]]}, [131425, None, 394275]], ['within caps', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[132425, False], [130425, False]]}, [132425, 130425]], ['mixed history', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[105255, True], [201448, True], [175992, True], [84220, False]]}, [105255, 201448, 175992, 167192]]], [['large increase phased in', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, False], [258006, False], [258006, False]]}, [148353, 170606, 196197]], ['large decrease capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[64501, False], [64501, False]]}, [122553, 116425]], ['coverage change exempt then capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, True], [387009, False]]}, [258006, 296707]], ['new business exempt', {'prior': 0, 'up': 150, 'down': 50, 'years': [[129003, False], [258006, False]]}, [129003, 148353]], ['lapse restarts as new business', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[129003, False], [None, False], [387009, False]]}, [129003, None, 387009]], ['within caps', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[130003, False], [128003, False]]}, [130003, 128003]], ['mixed history', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[151965, False], [114334, False], [235286, False], [180318, True]]}, [148353, 140935, 162075, 180318]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Phase-in steps jump because the next cap is measured from the indicated premium.

Input prior premium (0 = new business), up/down caps per mille, years [[indicated or None for a lapse, coverage_changed]]. A lapse outputs None and the next year is new business. New business or coverage changes charge the indicated premium; otherwise charge the indicated premium clamped to [prev*(1-down), prev*(1+up)] with bounds rounded half-up, where prev is last year's charged premium.

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):
    prev=x['prior']; out=[]
    for ind,changed in x['years']:
        if ind is None:
            out.append(None); prev=0; continue
        if changed:
            cur=ind
        else:
            hi=math.floor(Fraction(prev*(1000+x['up']),1000)+Fraction(1,2))
            lo=math.floor(Fraction(prev*(1000-x['down']),1000)+Fraction(1,2))
            cur=max(lo,min(hi,ind))
        out.append(cur); prev=cur
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['large increase phased in', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, False], [282332, False], [282332, False]]}, [156694, 173930, 193062]], ['large decrease capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[70583, False], [70583, False]]}, [134108, 127403]], ['coverage change exempt then capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, True], [423498, False]]}, [282332, 313389]], ['new business exempt', {'prior': 0, 'up': 110, 'down': 50, 'years': [[141166, False], [282332, False]]}, [141166, 156694]], ['lapse restarts as new business', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[141166, False], [None, False], [423498, False]]}, [141166, None, 423498]], ['within caps', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[142166, False], [140166, False]]}, [142166, 140166]], ['mixed history', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[172018, False], [166564, False], [197332, False], [213340, False]]}, [156694, 166564, 184886, 205223]]], [['large increase phased in', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, False], [163834, False], [163834, False]]}, [91747, 102757, 115088]], ['large decrease capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[40958, False], [40958, False]]}, [77821, 73930]], ['coverage change exempt then capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, True], [245751, False]]}, [163834, 183494]], ['new business exempt', {'prior': 0, 'up': 120, 'down': 50, 'years': [[81917, False], [163834, False]]}, [81917, 91747]], ['lapse restarts as new business', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[81917, False], [None, False], [245751, False]]}, [81917, None, 245751]], ['within caps', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[82917, False], [80917, False]]}, [82917, 80917]], ['mixed history', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[92584, False], [202024, False], [62931, True], [150823, False]]}, [91747, 102757, 62931, 70483]]], [['large increase phased in', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, False], [280726, False], [280726, False]]}, [158610, 179229, 202529]], ['large decrease capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[70181, False], [70181, False]]}, [133345, 126678]], ['coverage change exempt then capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, True], [421089, False]]}, [280726, 317220]], ['new business exempt', {'prior': 0, 'up': 130, 'down': 50, 'years': [[140363, False], [280726, False]]}, [140363, 158610]], ['lapse restarts as new business', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[140363, False], [None, False], [421089, False]]}, [140363, None, 421089]], ['within caps', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[141363, False], [139363, False]]}, [141363, 139363]], ['mixed history', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[224001, True], [54488, False], [53043, False], [82834, False]]}, [224001, 212801, 202161, 192053]]], [['large increase phased in', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, False], [262850, False], [262850, False]]}, [149825, 170801, 194713]], ['large decrease capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[65712, False], [65712, False]]}, [124854, 118611]], ['coverage change exempt then capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, True], [394275, False]]}, [262850, 299649]], ['new business exempt', {'prior': 0, 'up': 140, 'down': 50, 'years': [[131425, False], [262850, False]]}, [131425, 149825]], ['lapse restarts as new business', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[131425, False], [None, False], [394275, False]]}, [131425, None, 394275]], ['within caps', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[132425, False], [130425, False]]}, [132425, 130425]], ['mixed history', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[105255, True], [201448, True], [175992, True], [84220, False]]}, [105255, 201448, 175992, 167192]]], [['large increase phased in', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, False], [258006, False], [258006, False]]}, [148353, 170606, 196197]], ['large decrease capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[64501, False], [64501, False]]}, [122553, 116425]], ['coverage change exempt then capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, True], [387009, False]]}, [258006, 296707]], ['new business exempt', {'prior': 0, 'up': 150, 'down': 50, 'years': [[129003, False], [258006, False]]}, [129003, 148353]], ['lapse restarts as new business', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[129003, False], [None, False], [387009, False]]}, [129003, None, 387009]], ['within caps', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[130003, False], [128003, False]]}, [130003, 128003]], ['mixed history', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[151965, False], [114334, False], [235286, False], [180318, True]]}, [148353, 140935, 162075, 180318]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    prev=x['prior']; out=[]
    for ind,changed in x['years']:
        if ind is None:
            out.append(None); prev=0; continue
        if changed or ind==0:
            cur=ind
        else:
            hi=math.floor(Fraction(prev*(1000+x['up']),1000)+Fraction(1,2))
            lo=math.floor(Fraction(prev*(1000-x['down']),1000)+Fraction(1,2))
            cur=max(lo,min(hi,ind))
        out.append(cur); prev=cur
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['large increase phased in', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, False], [282332, False], [282332, False]]}, [156694, 173930, 193062]], ['large decrease capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[70583, False], [70583, False]]}, [134108, 127403]], ['coverage change exempt then capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, True], [423498, False]]}, [282332, 313389]], ['new business exempt', {'prior': 0, 'up': 110, 'down': 50, 'years': [[141166, False], [282332, False]]}, [141166, 156694]], ['lapse restarts as new business', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[141166, False], [None, False], [423498, False]]}, [141166, None, 423498]], ['within caps', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[142166, False], [140166, False]]}, [142166, 140166]], ['mixed history', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[172018, False], [166564, False], [197332, False], [213340, False]]}, [156694, 166564, 184886, 205223]]], [['large increase phased in', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, False], [163834, False], [163834, False]]}, [91747, 102757, 115088]], ['large decrease capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[40958, False], [40958, False]]}, [77821, 73930]], ['coverage change exempt then capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, True], [245751, False]]}, [163834, 183494]], ['new business exempt', {'prior': 0, 'up': 120, 'down': 50, 'years': [[81917, False], [163834, False]]}, [81917, 91747]], ['lapse restarts as new business', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[81917, False], [None, False], [245751, False]]}, [81917, None, 245751]], ['within caps', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[82917, False], [80917, False]]}, [82917, 80917]], ['mixed history', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[92584, False], [202024, False], [62931, True], [150823, False]]}, [91747, 102757, 62931, 70483]]], [['large increase phased in', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, False], [280726, False], [280726, False]]}, [158610, 179229, 202529]], ['large decrease capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[70181, False], [70181, False]]}, [133345, 126678]], ['coverage change exempt then capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, True], [421089, False]]}, [280726, 317220]], ['new business exempt', {'prior': 0, 'up': 130, 'down': 50, 'years': [[140363, False], [280726, False]]}, [140363, 158610]], ['lapse restarts as new business', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[140363, False], [None, False], [421089, False]]}, [140363, None, 421089]], ['within caps', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[141363, False], [139363, False]]}, [141363, 139363]], ['mixed history', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[224001, True], [54488, False], [53043, False], [82834, False]]}, [224001, 212801, 202161, 192053]]], [['large increase phased in', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, False], [262850, False], [262850, False]]}, [149825, 170801, 194713]], ['large decrease capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[65712, False], [65712, False]]}, [124854, 118611]], ['coverage change exempt then capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, True], [394275, False]]}, [262850, 299649]], ['new business exempt', {'prior': 0, 'up': 140, 'down': 50, 'years': [[131425, False], [262850, False]]}, [131425, 149825]], ['lapse restarts as new business', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[131425, False], [None, False], [394275, False]]}, [131425, None, 394275]], ['within caps', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[132425, False], [130425, False]]}, [132425, 130425]], ['mixed history', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[105255, True], [201448, True], [175992, True], [84220, False]]}, [105255, 201448, 175992, 167192]]], [['large increase phased in', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, False], [258006, False], [258006, False]]}, [148353, 170606, 196197]], ['large decrease capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[64501, False], [64501, False]]}, [122553, 116425]], ['coverage change exempt then capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, True], [387009, False]]}, [258006, 296707]], ['new business exempt', {'prior': 0, 'up': 150, 'down': 50, 'years': [[129003, False], [258006, False]]}, [129003, 148353]], ['lapse restarts as new business', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[129003, False], [None, False], [387009, False]]}, [129003, None, 387009]], ['within caps', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[130003, False], [128003, False]]}, [130003, 128003]], ['mixed history', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[151965, False], [114334, False], [235286, False], [180318, True]]}, [148353, 140935, 162075, 180318]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
New business is charged zero premium.

Input prior premium (0 = new business), up/down caps per mille, years [[indicated or None for a lapse, coverage_changed]]. A lapse outputs None and the next year is new business. New business or coverage changes charge the indicated premium; otherwise charge the indicated premium clamped to [prev*(1-down), prev*(1+up)] with bounds rounded half-up, where prev is last year's charged premium.

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):
    prev=x['prior']; out=[]
    for ind,changed in x['years']:
        if ind is None:
            out.append(None); prev=0; continue
        if changed or prev==0:
            cur=ind
        else:
            hi=math.floor(Fraction(prev*(1000+x['up']),1000)+Fraction(1,2))
            lo=math.floor(Fraction(prev*(1000-x['up']),1000)+Fraction(1,2))
            cur=max(lo,min(hi,ind))
        out.append(cur); prev=cur
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['large increase phased in', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, False], [282332, False], [282332, False]]}, [156694, 173930, 193062]], ['large decrease capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[70583, False], [70583, False]]}, [134108, 127403]], ['coverage change exempt then capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, True], [423498, False]]}, [282332, 313389]], ['new business exempt', {'prior': 0, 'up': 110, 'down': 50, 'years': [[141166, False], [282332, False]]}, [141166, 156694]], ['lapse restarts as new business', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[141166, False], [None, False], [423498, False]]}, [141166, None, 423498]], ['within caps', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[142166, False], [140166, False]]}, [142166, 140166]], ['mixed history', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[172018, False], [166564, False], [197332, False], [213340, False]]}, [156694, 166564, 184886, 205223]]], [['large increase phased in', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, False], [163834, False], [163834, False]]}, [91747, 102757, 115088]], ['large decrease capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[40958, False], [40958, False]]}, [77821, 73930]], ['coverage change exempt then capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, True], [245751, False]]}, [163834, 183494]], ['new business exempt', {'prior': 0, 'up': 120, 'down': 50, 'years': [[81917, False], [163834, False]]}, [81917, 91747]], ['lapse restarts as new business', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[81917, False], [None, False], [245751, False]]}, [81917, None, 245751]], ['within caps', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[82917, False], [80917, False]]}, [82917, 80917]], ['mixed history', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[92584, False], [202024, False], [62931, True], [150823, False]]}, [91747, 102757, 62931, 70483]]], [['large increase phased in', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, False], [280726, False], [280726, False]]}, [158610, 179229, 202529]], ['large decrease capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[70181, False], [70181, False]]}, [133345, 126678]], ['coverage change exempt then capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, True], [421089, False]]}, [280726, 317220]], ['new business exempt', {'prior': 0, 'up': 130, 'down': 50, 'years': [[140363, False], [280726, False]]}, [140363, 158610]], ['lapse restarts as new business', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[140363, False], [None, False], [421089, False]]}, [140363, None, 421089]], ['within caps', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[141363, False], [139363, False]]}, [141363, 139363]], ['mixed history', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[224001, True], [54488, False], [53043, False], [82834, False]]}, [224001, 212801, 202161, 192053]]], [['large increase phased in', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, False], [262850, False], [262850, False]]}, [149825, 170801, 194713]], ['large decrease capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[65712, False], [65712, False]]}, [124854, 118611]], ['coverage change exempt then capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, True], [394275, False]]}, [262850, 299649]], ['new business exempt', {'prior': 0, 'up': 140, 'down': 50, 'years': [[131425, False], [262850, False]]}, [131425, 149825]], ['lapse restarts as new business', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[131425, False], [None, False], [394275, False]]}, [131425, None, 394275]], ['within caps', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[132425, False], [130425, False]]}, [132425, 130425]], ['mixed history', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[105255, True], [201448, True], [175992, True], [84220, False]]}, [105255, 201448, 175992, 167192]]], [['large increase phased in', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, False], [258006, False], [258006, False]]}, [148353, 170606, 196197]], ['large decrease capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[64501, False], [64501, False]]}, [122553, 116425]], ['coverage change exempt then capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, True], [387009, False]]}, [258006, 296707]], ['new business exempt', {'prior': 0, 'up': 150, 'down': 50, 'years': [[129003, False], [258006, False]]}, [129003, 148353]], ['lapse restarts as new business', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[129003, False], [None, False], [387009, False]]}, [129003, None, 387009]], ['within caps', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[130003, False], [128003, False]]}, [130003, 128003]], ['mixed history', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[151965, False], [114334, False], [235286, False], [180318, True]]}, [148353, 140935, 162075, 180318]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    prev=x['prior']; out=[]
    for ind,changed in x['years']:
        if ind is None:
            out.append(None); prev=0; continue
        if changed or prev==0:
            cur=ind
        else:
            hi=math.floor(Fraction(prev*(1000+x['up']),1000)+Fraction(1,2))
            lo=math.floor(Fraction(prev*x['down'],1000)+Fraction(1,2))
            cur=max(lo,min(hi,ind))
        out.append(cur); prev=cur
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['large increase phased in', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, False], [282332, False], [282332, False]]}, [156694, 173930, 193062]], ['large decrease capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[70583, False], [70583, False]]}, [134108, 127403]], ['coverage change exempt then capped', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[282332, True], [423498, False]]}, [282332, 313389]], ['new business exempt', {'prior': 0, 'up': 110, 'down': 50, 'years': [[141166, False], [282332, False]]}, [141166, 156694]], ['lapse restarts as new business', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[141166, False], [None, False], [423498, False]]}, [141166, None, 423498]], ['within caps', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[142166, False], [140166, False]]}, [142166, 140166]], ['mixed history', {'prior': 141166, 'up': 110, 'down': 50, 'years': [[172018, False], [166564, False], [197332, False], [213340, False]]}, [156694, 166564, 184886, 205223]]], [['large increase phased in', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, False], [163834, False], [163834, False]]}, [91747, 102757, 115088]], ['large decrease capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[40958, False], [40958, False]]}, [77821, 73930]], ['coverage change exempt then capped', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[163834, True], [245751, False]]}, [163834, 183494]], ['new business exempt', {'prior': 0, 'up': 120, 'down': 50, 'years': [[81917, False], [163834, False]]}, [81917, 91747]], ['lapse restarts as new business', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[81917, False], [None, False], [245751, False]]}, [81917, None, 245751]], ['within caps', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[82917, False], [80917, False]]}, [82917, 80917]], ['mixed history', {'prior': 81917, 'up': 120, 'down': 50, 'years': [[92584, False], [202024, False], [62931, True], [150823, False]]}, [91747, 102757, 62931, 70483]]], [['large increase phased in', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, False], [280726, False], [280726, False]]}, [158610, 179229, 202529]], ['large decrease capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[70181, False], [70181, False]]}, [133345, 126678]], ['coverage change exempt then capped', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[280726, True], [421089, False]]}, [280726, 317220]], ['new business exempt', {'prior': 0, 'up': 130, 'down': 50, 'years': [[140363, False], [280726, False]]}, [140363, 158610]], ['lapse restarts as new business', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[140363, False], [None, False], [421089, False]]}, [140363, None, 421089]], ['within caps', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[141363, False], [139363, False]]}, [141363, 139363]], ['mixed history', {'prior': 140363, 'up': 130, 'down': 50, 'years': [[224001, True], [54488, False], [53043, False], [82834, False]]}, [224001, 212801, 202161, 192053]]], [['large increase phased in', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, False], [262850, False], [262850, False]]}, [149825, 170801, 194713]], ['large decrease capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[65712, False], [65712, False]]}, [124854, 118611]], ['coverage change exempt then capped', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[262850, True], [394275, False]]}, [262850, 299649]], ['new business exempt', {'prior': 0, 'up': 140, 'down': 50, 'years': [[131425, False], [262850, False]]}, [131425, 149825]], ['lapse restarts as new business', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[131425, False], [None, False], [394275, False]]}, [131425, None, 394275]], ['within caps', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[132425, False], [130425, False]]}, [132425, 130425]], ['mixed history', {'prior': 131425, 'up': 140, 'down': 50, 'years': [[105255, True], [201448, True], [175992, True], [84220, False]]}, [105255, 201448, 175992, 167192]]], [['large increase phased in', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, False], [258006, False], [258006, False]]}, [148353, 170606, 196197]], ['large decrease capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[64501, False], [64501, False]]}, [122553, 116425]], ['coverage change exempt then capped', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[258006, True], [387009, False]]}, [258006, 296707]], ['new business exempt', {'prior': 0, 'up': 150, 'down': 50, 'years': [[129003, False], [258006, False]]}, [129003, 148353]], ['lapse restarts as new business', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[129003, False], [None, False], [387009, False]]}, [129003, None, 387009]], ['within caps', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[130003, False], [128003, False]]}, [130003, 128003]], ['mixed history', {'prior': 129003, 'up': 150, 'down': 50, 'years': [[151965, False], [114334, False], [235286, False], [180318, True]]}, [148353, 140935, 162075, 180318]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Premium decreases are capped at the increase percentage.

Input prior premium (0 = new business), up/down caps per mille, years [[indicated or None for a lapse, coverage_changed]]. A lapse outputs None and the next year is new business. New business or coverage changes charge the indicated premium; otherwise charge the indicated premium clamped to [prev*(1-down), prev*(1+up)] with bounds rounded half-up, where prev is last year's charged premium.

split: open-access