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

N = 1
observations = []
def solve(x):
    periods = x['periods']
    out = []
    for eid, date, adjusting in x['entries']:
        found = None
        for p in periods:
            if p[0] <= date <= p[1]:
                found = p
                break
        if found is None:
            out.append([eid, None, 'no_period'])
            continue
        status = found[2]
        if status == 'soft' and adjusting:
            status = 'open'
        if status == 'open':
            out.append([eid, date, 'posted'])
        elif x['policy'] == 'roll':
            nxt = [p for p in periods if p[0] > found[1] and p[2] == 'open']
            if nxt:
                out.append([eid, nxt[0][0], 'rolled'])
            else:
                out.append([eid, None, 'closed'])
        else:
            out.append([eid, None, 'closed'])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: period ordering', {'periods': [[61, 91, 'open'], [92, 122, 'soft'], [31, 60, 'open'], [1, 30, 'closed']], 'policy': 'roll', 'entries': [['E0', 30, True], ['E1', 95, True], ['E2', 60, False], ['E3', 4, False], ['E4', 60, True], ['E5', 31, False]]}, [['E0', 31, 'rolled'], ['E1', 95, 'posted'], ['E2', 60, 'posted'], ['E3', 31, 'rolled'], ['E4', 60, 'posted'], ['E5', 31, 'posted']]], ['control 1', {'periods': [[122, 151, 'soft'], [92, 121, 'soft'], [31, 60, 'closed'], [1, 30, 'soft'], [61, 91, 'open']], 'policy': 'reject', 'entries': [['E0', 151, False], ['E1', 125, False], ['E2', 121, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed']]], ['control 2', {'periods': [[31, 60, 'closed'], [61, 90, 'closed'], [1, 30, 'closed'], [91, 121, 'closed']], 'policy': 'roll', 'entries': [['E0', 63, False], ['E1', 121, False], ['E2', 94, True], ['E3', 1, False], ['E4', 34, False], ['E5', 61, True]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', None, 'closed'], ['E4', None, 'closed'], ['E5', None, 'closed']]], ['control 3', {'periods': [[92, 121, 'closed'], [32, 61, 'soft'], [62, 91, 'closed'], [1, 31, 'soft']], 'policy': 'roll', 'entries': [['E0', 35, False], ['E1', 65, False], ['E2', 92, True], ['E3', 35, True]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', 35, 'posted']]], ['control 4', {'periods': [[59, 88, 'soft'], [117, 146, 'open'], [31, 58, 'closed'], [89, 116, 'closed'], [1, 30, 'closed']], 'policy': 'roll', 'entries': [['E0', 120, False], ['E1', 31, True], ['E2', 59, False], ['E3', 120, False], ['E4', 59, True]]}, [['E0', 120, 'posted'], ['E1', 117, 'rolled'], ['E2', 117, 'rolled'], ['E3', 120, 'posted'], ['E4', 59, 'posted']]], ['control 5', {'periods': [[29, 58, 'open'], [1, 28, 'open']], 'policy': 'roll', 'entries': [['E0', 29, True], ['E1', 58, True], ['E2', 58, False], ['E3', 29, True]]}, [['E0', 29, 'posted'], ['E1', 58, 'posted'], ['E2', 58, 'posted'], ['E3', 29, 'posted']]], ['control 6', {'periods': [[29, 58, 'closed'], [90, 119, 'closed'], [1, 28, 'open'], [59, 89, 'soft']], 'policy': 'reject', 'entries': [['E0', 93, True], ['E1', 89, True], ['E2', 59, False]]}, [['E0', None, 'closed'], ['E1', 89, 'posted'], ['E2', None, 'closed']]]], [['regression: period ordering', {'periods': [[59, 86, 'open'], [1, 30, 'closed'], [31, 58, 'open']], 'policy': 'roll', 'entries': [['E0', 61, False], ['E1', 34, True], ['E2', 33, False], ['E3', 4, True], ['E4', 31, False]]}, [['E0', 61, 'posted'], ['E1', 34, 'posted'], ['E2', 33, 'posted'], ['E3', 31, 'rolled'], ['E4', 31, 'posted']]], ['control 1', {'periods': [[1, 31, 'closed'], [60, 90, 'soft'], [32, 59, 'closed']], 'policy': 'roll', 'entries': [['E0', 60, True], ['E1', 62, True], ['E2', 1, True], ['E3', 31, False], ['E4', 62, True]]}, [['E0', 60, 'posted'], ['E1', 62, 'posted'], ['E2', None, 'closed'], ['E3', None, 'closed'], ['E4', 62, 'posted']]], ['control 2', {'periods': [[93, 120, 'closed'], [121, 148, 'soft'], [63, 92, 'soft'], [1, 31, 'soft'], [32, 62, 'open']], 'policy': 'roll', 'entries': [['E0', 149, True], ['E1', 63, True], ['E2', 148, True], ['E3', 4, False]]}, [['E0', None, 'no_period'], ['E1', 63, 'posted'], ['E2', 148, 'posted'], ['E3', 32, 'rolled']]], ['control 3', {'periods': [[29, 59, 'closed'], [1, 28, 'closed'], [65, 94, 'open']], 'policy': 'reject', 'entries': [['E0', 68, False], ['E1', 97, False], ['E2', 95, True], ['E3', 68, False], ['E4', 28, False], ['E5', 28, False]]}, [['E0', 68, 'posted'], ['E1', None, 'no_period'], ['E2', None, 'no_period'], ['E3', 68, 'posted'], ['E4', None, 'closed'], ['E5', None, 'closed']]], ['control 4', {'periods': [[62, 89, 'open'], [1, 31, 'soft'], [32, 61, 'closed'], [90, 117, 'closed']], 'policy': 'reject', 'entries': [['E0', 62, False], ['E1', 117, False], ['E2', 93, False], ['E3', 65, False]]}, [['E0', 62, 'posted'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', 65, 'posted']]], ['control 5', {'periods': [[29, 59, 'open'], [1, 28, 'closed'], [60, 90, 'closed']], 'policy': 'roll', 'entries': [['E0', 31, False], ['E1', 62, True], ['E2', 29, False], ['E3', 93, False], ['E4', 59, False], ['E5', 60, True]]}, [['E0', 31, 'posted'], ['E1', None, 'closed'], ['E2', 29, 'posted'], ['E3', None, 'no_period'], ['E4', 59, 'posted'], ['E5', None, 'closed']]], ['control 6', {'periods': [[65, 92, 'open'], [34, 64, 'closed'], [1, 28, 'closed']], 'policy': 'reject', 'entries': [['E0', 67, False], ['E1', 1, False], ['E2', 64, True], ['E3', 68, False]]}, [['E0', 67, 'posted'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', 68, 'posted']]]], [['regression: period ordering', {'periods': [[65, 92, 'open'], [1, 28, 'soft'], [29, 59, 'open'], [93, 122, 'closed']], 'policy': 'roll', 'entries': [['E0', 93, False], ['E1', 28, True], ['E2', 28, False], ['E3', 29, False]]}, [['E0', None, 'closed'], ['E1', 28, 'posted'], ['E2', 29, 'rolled'], ['E3', 29, 'posted']]], ['control 1', {'periods': [[1, 30, 'soft'], [31, 60, 'soft']], 'policy': 'roll', 'entries': [['E0', 30, False], ['E1', 31, False], ['E2', 31, True], ['E3', 30, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', 31, 'posted'], ['E3', None, 'closed']]], ['control 2', {'periods': [[1, 28, 'closed'], [29, 59, 'closed']], 'policy': 'roll', 'entries': [['E0', 29, True], ['E1', 31, False], ['E2', 1, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed']]], ['control 3', {'periods': [[1, 28, 'open'], [29, 59, 'soft']], 'policy': 'roll', 'entries': [['E0', 1, False], ['E1', 29, False], ['E2', 31, False]]}, [['E0', 1, 'posted'], ['E1', None, 'closed'], ['E2', None, 'closed']]], ['control 4', {'periods': [[65, 92, 'open'], [1, 28, 'closed'], [34, 64, 'soft']], 'policy': 'roll', 'entries': [['E0', 65, False], ['E1', 65, False], ['E2', 92, False]]}, [['E0', 65, 'posted'], ['E1', 65, 'posted'], ['E2', 92, 'posted']]], ['control 5', {'periods': [[63, 90, 'open'], [1, 31, 'closed'], [32, 62, 'closed']], 'policy': 'roll', 'entries': [['E0', 63, True], ['E1', 65, True], ['E2', 63, True], ['E3', 1, False]]}, [['E0', 63, 'posted'], ['E1', 65, 'posted'], ['E2', 63, 'posted'], ['E3', 63, 'rolled']]], ['control 6', {'periods': [[29, 59, 'soft'], [123, 150, 'closed'], [1, 28, 'closed'], [60, 87, 'closed'], [93, 122, 'closed']], 'policy': 'roll', 'entries': [['E0', 29, False], ['E1', 29, False], ['E2', 63, False], ['E3', 29, False], ['E4', 151, False], ['E5', 60, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', None, 'closed'], ['E4', None, 'no_period'], ['E5', None, 'closed']]]], [['regression: period ordering', {'periods': [[65, 95, 'open'], [29, 59, 'open'], [1, 28, 'closed']], 'policy': 'roll', 'entries': [['E0', 29, True], ['E1', 29, False], ['E2', 28, False], ['E3', 59, False]]}, [['E0', 29, 'posted'], ['E1', 29, 'posted'], ['E2', 29, 'rolled'], ['E3', 59, 'posted']]], ['control 1', {'periods': [[29, 58, 'closed'], [1, 28, 'open']], 'policy': 'roll', 'entries': [['E0', 61, False], ['E1', 1, False], ['E2', 58, True]]}, [['E0', None, 'no_period'], ['E1', 1, 'posted'], ['E2', None, 'closed']]], ['control 2', {'periods': [[59, 86, 'open'], [29, 58, 'closed'], [1, 28, 'closed']], 'policy': 'roll', 'entries': [['E0', 59, False], ['E1', 87, False], ['E2', 87, False], ['E3', 61, False]]}, [['E0', 59, 'posted'], ['E1', None, 'no_period'], ['E2', None, 'no_period'], ['E3', 61, 'posted']]], ['control 3', {'periods': [[1, 31, 'soft'], [32, 59, 'open']], 'policy': 'reject', 'entries': [['E0', 60, True], ['E1', 32, False], ['E2', 62, False]]}, [['E0', None, 'no_period'], ['E1', 32, 'posted'], ['E2', None, 'no_period']]], ['control 4', {'periods': [[34, 61, 'soft'], [62, 92, 'open'], [1, 28, 'soft'], [93, 123, 'open']], 'policy': 'roll', 'entries': [['E0', 28, True], ['E1', 65, True], ['E2', 29, False], ['E3', 65, False], ['E4', 93, True]]}, [['E0', 28, 'posted'], ['E1', 65, 'posted'], ['E2', None, 'no_period'], ['E3', 65, 'posted'], ['E4', 93, 'posted']]], ['control 5', {'periods': [[37, 66, 'soft'], [1, 31, 'closed']], 'policy': 'roll', 'entries': [['E0', 37, False], ['E1', 67, True], ['E2', 69, False]]}, [['E0', None, 'closed'], ['E1', None, 'no_period'], ['E2', None, 'no_period']]], ['control 6', {'periods': [[63, 92, 'closed'], [1, 31, 'closed'], [98, 125, 'open'], [32, 62, 'soft']], 'policy': 'roll', 'entries': [['E0', 32, True], ['E1', 63, False], ['E2', 93, False]]}, [['E0', 32, 'posted'], ['E1', 98, 'rolled'], ['E2', None, 'no_period']]]], [['regression: period ordering', {'periods': [[1, 28, 'closed'], [59, 88, 'closed'], [120, 149, 'open'], [29, 58, 'soft'], [89, 119, 'open']], 'policy': 'roll', 'entries': [['E0', 29, False], ['E1', 91, False], ['E2', 59, True], ['E3', 150, False], ['E4', 119, False]]}, [['E0', 89, 'rolled'], ['E1', 91, 'posted'], ['E2', 89, 'rolled'], ['E3', None, 'no_period'], ['E4', 119, 'posted']]], ['control 1', {'periods': [[1, 28, 'closed'], [29, 59, 'closed'], [60, 89, 'soft']], 'policy': 'roll', 'entries': [['E0', 63, False], ['E1', 32, True], ['E2', 63, True]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', 63, 'posted']]], ['control 2', {'periods': [[34, 61, 'closed'], [1, 28, 'soft'], [67, 94, 'open'], [95, 122, 'open']], 'policy': 'roll', 'entries': [['E0', 95, True], ['E1', 37, False], ['E2', 94, False]]}, [['E0', 95, 'posted'], ['E1', 67, 'rolled'], ['E2', 94, 'posted']]], ['control 3', {'periods': [[128, 155, 'open'], [31, 58, 'closed'], [1, 30, 'soft'], [59, 86, 'closed'], [92, 122, 'soft']], 'policy': 'reject', 'entries': [['E0', 125, False], ['E1', 31, False], ['E2', 156, True], ['E3', 1, False], ['E4', 95, False], ['E5', 95, False]]}, [['E0', None, 'no_period'], ['E1', None, 'closed'], ['E2', None, 'no_period'], ['E3', None, 'closed'], ['E4', None, 'closed'], ['E5', None, 'closed']]], ['control 4', {'periods': [[31, 61, 'soft'], [62, 91, 'closed'], [92, 121, 'closed'], [1, 30, 'closed']], 'policy': 'reject', 'entries': [['E0', 34, False], ['E1', 92, False], ['E2', 30, False], ['E3', 1, False], ['E4', 31, True], ['E5', 124, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', None, 'closed'], ['E4', 31, 'posted'], ['E5', None, 'no_period']]], ['control 5', {'periods': [[93, 123, 'closed'], [1, 31, 'open'], [62, 92, 'closed'], [32, 61, 'closed']], 'policy': 'reject', 'entries': [['E0', 123, False], ['E1', 95, True], ['E2', 32, True], ['E3', 1, False], ['E4', 124, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', 1, 'posted'], ['E4', None, 'no_period']]], ['control 6', {'periods': [[73, 100, 'open'], [1, 31, 'closed'], [37, 67, 'open'], [129, 159, 'open'], [101, 128, 'soft']], 'policy': 'reject', 'entries': [['E0', 129, False], ['E1', 40, True], ['E2', 132, True], ['E3', 73, False], ['E4', 132, False], ['E5', 34, False]]}, [['E0', 129, 'posted'], ['E1', 40, 'posted'], ['E2', 132, 'posted'], ['E3', 73, 'posted'], ['E4', 132, 'posted'], ['E5', None, 'no_period']]]]]
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):
    periods = sorted(x['periods'], key=lambda p: p[1], reverse=True)
    out = []
    for eid, date, adjusting in x['entries']:
        found = None
        for p in periods:
            if p[0] <= date <= p[1]:
                found = p
                break
        if found is None:
            out.append([eid, None, 'no_period'])
            continue
        status = found[2]
        if status == 'soft' and adjusting:
            status = 'open'
        if status == 'open':
            out.append([eid, date, 'posted'])
        elif x['policy'] == 'roll':
            nxt = [p for p in periods if p[0] > found[1] and p[2] == 'open']
            if nxt:
                out.append([eid, nxt[0][0], 'rolled'])
            else:
                out.append([eid, None, 'closed'])
        else:
            out.append([eid, None, 'closed'])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: period ordering', {'periods': [[61, 91, 'open'], [92, 122, 'soft'], [31, 60, 'open'], [1, 30, 'closed']], 'policy': 'roll', 'entries': [['E0', 30, True], ['E1', 95, True], ['E2', 60, False], ['E3', 4, False], ['E4', 60, True], ['E5', 31, False]]}, [['E0', 31, 'rolled'], ['E1', 95, 'posted'], ['E2', 60, 'posted'], ['E3', 31, 'rolled'], ['E4', 60, 'posted'], ['E5', 31, 'posted']]], ['control 1', {'periods': [[122, 151, 'soft'], [92, 121, 'soft'], [31, 60, 'closed'], [1, 30, 'soft'], [61, 91, 'open']], 'policy': 'reject', 'entries': [['E0', 151, False], ['E1', 125, False], ['E2', 121, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed']]], ['control 2', {'periods': [[31, 60, 'closed'], [61, 90, 'closed'], [1, 30, 'closed'], [91, 121, 'closed']], 'policy': 'roll', 'entries': [['E0', 63, False], ['E1', 121, False], ['E2', 94, True], ['E3', 1, False], ['E4', 34, False], ['E5', 61, True]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', None, 'closed'], ['E4', None, 'closed'], ['E5', None, 'closed']]], ['control 3', {'periods': [[92, 121, 'closed'], [32, 61, 'soft'], [62, 91, 'closed'], [1, 31, 'soft']], 'policy': 'roll', 'entries': [['E0', 35, False], ['E1', 65, False], ['E2', 92, True], ['E3', 35, True]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', 35, 'posted']]], ['control 4', {'periods': [[59, 88, 'soft'], [117, 146, 'open'], [31, 58, 'closed'], [89, 116, 'closed'], [1, 30, 'closed']], 'policy': 'roll', 'entries': [['E0', 120, False], ['E1', 31, True], ['E2', 59, False], ['E3', 120, False], ['E4', 59, True]]}, [['E0', 120, 'posted'], ['E1', 117, 'rolled'], ['E2', 117, 'rolled'], ['E3', 120, 'posted'], ['E4', 59, 'posted']]], ['control 5', {'periods': [[29, 58, 'open'], [1, 28, 'open']], 'policy': 'roll', 'entries': [['E0', 29, True], ['E1', 58, True], ['E2', 58, False], ['E3', 29, True]]}, [['E0', 29, 'posted'], ['E1', 58, 'posted'], ['E2', 58, 'posted'], ['E3', 29, 'posted']]], ['control 6', {'periods': [[29, 58, 'closed'], [90, 119, 'closed'], [1, 28, 'open'], [59, 89, 'soft']], 'policy': 'reject', 'entries': [['E0', 93, True], ['E1', 89, True], ['E2', 59, False]]}, [['E0', None, 'closed'], ['E1', 89, 'posted'], ['E2', None, 'closed']]]], [['regression: period ordering', {'periods': [[59, 86, 'open'], [1, 30, 'closed'], [31, 58, 'open']], 'policy': 'roll', 'entries': [['E0', 61, False], ['E1', 34, True], ['E2', 33, False], ['E3', 4, True], ['E4', 31, False]]}, [['E0', 61, 'posted'], ['E1', 34, 'posted'], ['E2', 33, 'posted'], ['E3', 31, 'rolled'], ['E4', 31, 'posted']]], ['control 1', {'periods': [[1, 31, 'closed'], [60, 90, 'soft'], [32, 59, 'closed']], 'policy': 'roll', 'entries': [['E0', 60, True], ['E1', 62, True], ['E2', 1, True], ['E3', 31, False], ['E4', 62, True]]}, [['E0', 60, 'posted'], ['E1', 62, 'posted'], ['E2', None, 'closed'], ['E3', None, 'closed'], ['E4', 62, 'posted']]], ['control 2', {'periods': [[93, 120, 'closed'], [121, 148, 'soft'], [63, 92, 'soft'], [1, 31, 'soft'], [32, 62, 'open']], 'policy': 'roll', 'entries': [['E0', 149, True], ['E1', 63, True], ['E2', 148, True], ['E3', 4, False]]}, [['E0', None, 'no_period'], ['E1', 63, 'posted'], ['E2', 148, 'posted'], ['E3', 32, 'rolled']]], ['control 3', {'periods': [[29, 59, 'closed'], [1, 28, 'closed'], [65, 94, 'open']], 'policy': 'reject', 'entries': [['E0', 68, False], ['E1', 97, False], ['E2', 95, True], ['E3', 68, False], ['E4', 28, False], ['E5', 28, False]]}, [['E0', 68, 'posted'], ['E1', None, 'no_period'], ['E2', None, 'no_period'], ['E3', 68, 'posted'], ['E4', None, 'closed'], ['E5', None, 'closed']]], ['control 4', {'periods': [[62, 89, 'open'], [1, 31, 'soft'], [32, 61, 'closed'], [90, 117, 'closed']], 'policy': 'reject', 'entries': [['E0', 62, False], ['E1', 117, False], ['E2', 93, False], ['E3', 65, False]]}, [['E0', 62, 'posted'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', 65, 'posted']]], ['control 5', {'periods': [[29, 59, 'open'], [1, 28, 'closed'], [60, 90, 'closed']], 'policy': 'roll', 'entries': [['E0', 31, False], ['E1', 62, True], ['E2', 29, False], ['E3', 93, False], ['E4', 59, False], ['E5', 60, True]]}, [['E0', 31, 'posted'], ['E1', None, 'closed'], ['E2', 29, 'posted'], ['E3', None, 'no_period'], ['E4', 59, 'posted'], ['E5', None, 'closed']]], ['control 6', {'periods': [[65, 92, 'open'], [34, 64, 'closed'], [1, 28, 'closed']], 'policy': 'reject', 'entries': [['E0', 67, False], ['E1', 1, False], ['E2', 64, True], ['E3', 68, False]]}, [['E0', 67, 'posted'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', 68, 'posted']]]], [['regression: period ordering', {'periods': [[65, 92, 'open'], [1, 28, 'soft'], [29, 59, 'open'], [93, 122, 'closed']], 'policy': 'roll', 'entries': [['E0', 93, False], ['E1', 28, True], ['E2', 28, False], ['E3', 29, False]]}, [['E0', None, 'closed'], ['E1', 28, 'posted'], ['E2', 29, 'rolled'], ['E3', 29, 'posted']]], ['control 1', {'periods': [[1, 30, 'soft'], [31, 60, 'soft']], 'policy': 'roll', 'entries': [['E0', 30, False], ['E1', 31, False], ['E2', 31, True], ['E3', 30, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', 31, 'posted'], ['E3', None, 'closed']]], ['control 2', {'periods': [[1, 28, 'closed'], [29, 59, 'closed']], 'policy': 'roll', 'entries': [['E0', 29, True], ['E1', 31, False], ['E2', 1, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed']]], ['control 3', {'periods': [[1, 28, 'open'], [29, 59, 'soft']], 'policy': 'roll', 'entries': [['E0', 1, False], ['E1', 29, False], ['E2', 31, False]]}, [['E0', 1, 'posted'], ['E1', None, 'closed'], ['E2', None, 'closed']]], ['control 4', {'periods': [[65, 92, 'open'], [1, 28, 'closed'], [34, 64, 'soft']], 'policy': 'roll', 'entries': [['E0', 65, False], ['E1', 65, False], ['E2', 92, False]]}, [['E0', 65, 'posted'], ['E1', 65, 'posted'], ['E2', 92, 'posted']]], ['control 5', {'periods': [[63, 90, 'open'], [1, 31, 'closed'], [32, 62, 'closed']], 'policy': 'roll', 'entries': [['E0', 63, True], ['E1', 65, True], ['E2', 63, True], ['E3', 1, False]]}, [['E0', 63, 'posted'], ['E1', 65, 'posted'], ['E2', 63, 'posted'], ['E3', 63, 'rolled']]], ['control 6', {'periods': [[29, 59, 'soft'], [123, 150, 'closed'], [1, 28, 'closed'], [60, 87, 'closed'], [93, 122, 'closed']], 'policy': 'roll', 'entries': [['E0', 29, False], ['E1', 29, False], ['E2', 63, False], ['E3', 29, False], ['E4', 151, False], ['E5', 60, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', None, 'closed'], ['E4', None, 'no_period'], ['E5', None, 'closed']]]], [['regression: period ordering', {'periods': [[65, 95, 'open'], [29, 59, 'open'], [1, 28, 'closed']], 'policy': 'roll', 'entries': [['E0', 29, True], ['E1', 29, False], ['E2', 28, False], ['E3', 59, False]]}, [['E0', 29, 'posted'], ['E1', 29, 'posted'], ['E2', 29, 'rolled'], ['E3', 59, 'posted']]], ['control 1', {'periods': [[29, 58, 'closed'], [1, 28, 'open']], 'policy': 'roll', 'entries': [['E0', 61, False], ['E1', 1, False], ['E2', 58, True]]}, [['E0', None, 'no_period'], ['E1', 1, 'posted'], ['E2', None, 'closed']]], ['control 2', {'periods': [[59, 86, 'open'], [29, 58, 'closed'], [1, 28, 'closed']], 'policy': 'roll', 'entries': [['E0', 59, False], ['E1', 87, False], ['E2', 87, False], ['E3', 61, False]]}, [['E0', 59, 'posted'], ['E1', None, 'no_period'], ['E2', None, 'no_period'], ['E3', 61, 'posted']]], ['control 3', {'periods': [[1, 31, 'soft'], [32, 59, 'open']], 'policy': 'reject', 'entries': [['E0', 60, True], ['E1', 32, False], ['E2', 62, False]]}, [['E0', None, 'no_period'], ['E1', 32, 'posted'], ['E2', None, 'no_period']]], ['control 4', {'periods': [[34, 61, 'soft'], [62, 92, 'open'], [1, 28, 'soft'], [93, 123, 'open']], 'policy': 'roll', 'entries': [['E0', 28, True], ['E1', 65, True], ['E2', 29, False], ['E3', 65, False], ['E4', 93, True]]}, [['E0', 28, 'posted'], ['E1', 65, 'posted'], ['E2', None, 'no_period'], ['E3', 65, 'posted'], ['E4', 93, 'posted']]], ['control 5', {'periods': [[37, 66, 'soft'], [1, 31, 'closed']], 'policy': 'roll', 'entries': [['E0', 37, False], ['E1', 67, True], ['E2', 69, False]]}, [['E0', None, 'closed'], ['E1', None, 'no_period'], ['E2', None, 'no_period']]], ['control 6', {'periods': [[63, 92, 'closed'], [1, 31, 'closed'], [98, 125, 'open'], [32, 62, 'soft']], 'policy': 'roll', 'entries': [['E0', 32, True], ['E1', 63, False], ['E2', 93, False]]}, [['E0', 32, 'posted'], ['E1', 98, 'rolled'], ['E2', None, 'no_period']]]], [['regression: period ordering', {'periods': [[1, 28, 'closed'], [59, 88, 'closed'], [120, 149, 'open'], [29, 58, 'soft'], [89, 119, 'open']], 'policy': 'roll', 'entries': [['E0', 29, False], ['E1', 91, False], ['E2', 59, True], ['E3', 150, False], ['E4', 119, False]]}, [['E0', 89, 'rolled'], ['E1', 91, 'posted'], ['E2', 89, 'rolled'], ['E3', None, 'no_period'], ['E4', 119, 'posted']]], ['control 1', {'periods': [[1, 28, 'closed'], [29, 59, 'closed'], [60, 89, 'soft']], 'policy': 'roll', 'entries': [['E0', 63, False], ['E1', 32, True], ['E2', 63, True]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', 63, 'posted']]], ['control 2', {'periods': [[34, 61, 'closed'], [1, 28, 'soft'], [67, 94, 'open'], [95, 122, 'open']], 'policy': 'roll', 'entries': [['E0', 95, True], ['E1', 37, False], ['E2', 94, False]]}, [['E0', 95, 'posted'], ['E1', 67, 'rolled'], ['E2', 94, 'posted']]], ['control 3', {'periods': [[128, 155, 'open'], [31, 58, 'closed'], [1, 30, 'soft'], [59, 86, 'closed'], [92, 122, 'soft']], 'policy': 'reject', 'entries': [['E0', 125, False], ['E1', 31, False], ['E2', 156, True], ['E3', 1, False], ['E4', 95, False], ['E5', 95, False]]}, [['E0', None, 'no_period'], ['E1', None, 'closed'], ['E2', None, 'no_period'], ['E3', None, 'closed'], ['E4', None, 'closed'], ['E5', None, 'closed']]], ['control 4', {'periods': [[31, 61, 'soft'], [62, 91, 'closed'], [92, 121, 'closed'], [1, 30, 'closed']], 'policy': 'reject', 'entries': [['E0', 34, False], ['E1', 92, False], ['E2', 30, False], ['E3', 1, False], ['E4', 31, True], ['E5', 124, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', None, 'closed'], ['E4', 31, 'posted'], ['E5', None, 'no_period']]], ['control 5', {'periods': [[93, 123, 'closed'], [1, 31, 'open'], [62, 92, 'closed'], [32, 61, 'closed']], 'policy': 'reject', 'entries': [['E0', 123, False], ['E1', 95, True], ['E2', 32, True], ['E3', 1, False], ['E4', 124, False]]}, [['E0', None, 'closed'], ['E1', None, 'closed'], ['E2', None, 'closed'], ['E3', 1, 'posted'], ['E4', None, 'no_period']]], ['control 6', {'periods': [[73, 100, 'open'], [1, 31, 'closed'], [37, 67, 'open'], [129, 159, 'open'], [101, 128, 'soft']], 'policy': 'reject', 'entries': [['E0', 129, False], ['E1', 40, True], ['E2', 132, True], ['E3', 73, False], ['E4', 132, False], ['E5', 34, False]]}, [['E0', 129, 'posted'], ['E1', 40, 'posted'], ['E2', 132, 'posted'], ['E3', 73, 'posted'], ['E4', 132, 'posted'], ['E5', None, 'no_period']]]]]
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:
Roll-forward destinations depend on the order periods were configured.

x = {'periods': [[start_day, end_day, 'open'|'soft'|'closed']] (non-overlapping, any order), 'policy': 'reject'|'roll', 'entries': [[id, day, adjusting]]}. The period containing the day (start and end inclusive) is found; none gives [id, None, 'no_period']. Soft periods accept adjusting entries only. Open acceptance gives [id, day, 'posted']. Otherwise under 'roll' the entry posts on the start day of the earliest later open period ([id, start, 'rolled']) and with none, or under 'reject', gives [id, None, 'closed'].

split: open-access


meaning: Fixture-count band, not measured model difficulty

deps: stdlib

prompt:
A liability ledger shows credits as decreases in the running balance.

x = {'normal': 'D'|'C', 'opening': balance before all lines, 'lines': [[seq, day, side, amount]], 'from': day, 'to': day}. Balances are signed positive on the normal side. The report opening is the opening plus every line dated before 'from'. Lines dated from..to inclusive are listed in (day, seq) order with the running balance after each; closing is the last running balance (the report opening if none). Return {'opening', 'rows': [[seq, day, running]], 'closing'}.

split: open-access


prompt:
Back-dated entries appear at the end of the ledger with wrong running balances.

x = {'normal': 'D'|'C', 'opening': balance before all lines, 'lines': [[seq, day, side, amount]], 'from': day, 'to': day}. Balances are signed positive on the normal side. The report opening is the opening plus every line dated before 'from'. Lines dated from..to inclusive are listed in (day, seq) order with the running balance after each; closing is the last running balance (the report opening if none). Return {'opening', 'rows': [[seq, day, running]], 'closing'}.

split: open-access


prompt:
Lines dated on the first report day are counted in the opening and again in the rows.

x = {'normal': 'D'|'C', 'opening': balance before all lines, 'lines': [[seq, day, side, amount]], 'from': day, 'to': day}. Balances are signed positive on the normal side. The report opening is the opening plus every line dated before 'from'. Lines dated from..to inclusive are listed in (day, seq) order with the running balance after each; closing is the last running balance (the report opening if none). Return {'opening', 'rows': [[seq, day, running]], 'closing'}.

split: open-access


prompt:
Entries dated on the report end day are missing from the report.

x = {'normal': 'D'|'C', 'opening': balance before all lines, 'lines': [[seq, day, side, amount]], 'from': day, 'to': day}. Balances are signed positive on the normal side. The report opening is the opening plus every line dated before 'from'. Lines dated from..to inclusive are listed in (day, seq) order with the running balance after each; closing is the last running balance (the report opening if none). Return {'opening', 'rows': [[seq, day, running]], 'closing'}.

split: open-access


prompt:
Running balances in the report start from zero.

x = {'normal': 'D'|'C', 'opening': balance before all lines, 'lines': [[seq, day, side, amount]], 'from': day, 'to': day}. Balances are signed positive on the normal side. The report opening is the opening plus every line dated before 'from'. Lines dated from..to inclusive are listed in (day, seq) order with the running balance after each; closing is the last running balance (the report opening if none). Return {'opening', 'rows': [[seq, day, running]], 'closing'}.

split: open-access


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

N = 1
observations = []
def solve(x):
    layers = []
    cogs = revenue = 0
    short = []
    for i, ev in enumerate(x):
        if ev[0] == 'buy':
            if layers and layers[-1][1] == ev[2]:
                layers[-1][0] += ev[1]
            else:
                layers.append([ev[1], ev[2]])
        elif ev[0] == 'sell':
            qty = ev[1]
            if qty > sum(l[0] for l in layers):
                short.append(i)
                continue
            revenue += qty * ev[2]
            while qty:
                head = layers[-1]
                take = min(qty, head[0])
                cogs += take * head[1]
                head[0] -= take
                qty -= take
                if head[0] == 0:
                    layers.pop()
        elif ev[0] == 'purchase_return':
            match = [l for l in layers if l[1] == ev[2] and l[0] >= ev[1]]
            if not match:
                short.append(i)
                continue
            match[-1][0] -= ev[1]
            if match[-1][0] == 0:
                layers.remove(match[-1])
    inventory = sum(q * c for q, c in layers)
    return {'cogs': cogs, 'revenue': revenue, 'inventory': inventory, 'layers': layers, 'rejected': short}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: consumption order', [['buy', 5, 120], ['sell', 6, 200], ['sell', 3, 200], ['buy', 1, 100], ['buy', 5, 120], ['buy', 5, 100], ['sell', 6, 200], ['sell', 12, 250]], {'cogs': 1060, 'revenue': 1800, 'inventory': 740, 'layers': [[2, 120], [5, 100]], 'rejected': [1, 7]}], ['control 1', [['sell', 3, 250], ['buy', 2, 120], ['purchase_return', 1, 100], ['buy', 5, 100], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 980, 'layers': [[2, 120], [5, 100], [2, 120]], 'rejected': [0, 2]}], ['control 2', [['buy', 5, 150], ['sell', 3, 250], ['sell', 2, 250], ['buy', 10, 100], ['buy', 10, 120], ['purchase_return', 2, 100], ['purchase_return', 5, 100], ['buy', 10, 150], ['buy', 2, 120], ['purchase_return', 5, 100]], {'cogs': 750, 'revenue': 1250, 'inventory': 3240, 'layers': [[3, 100], [10, 120], [10, 150], [2, 120]], 'rejected': [9]}], ['control 3', [['buy', 1, 120], ['sell', 12, 200], ['sell', 2, 250], ['sell', 2, 250]], {'cogs': 0, 'revenue': 0, 'inventory': 120, 'layers': [[1, 120]], 'rejected': [1, 2, 3]}], ['control 4', [['buy', 5, 100], ['sell', 3, 250], ['sell', 12, 200]], {'cogs': 300, 'revenue': 750, 'inventory': 200, 'layers': [[2, 100]], 'rejected': [2]}], ['control 5', [['buy', 10, 120], ['purchase_return', 1, 100], ['sell', 1, 200], ['purchase_return', 2, 100], ['sell', 2, 200], ['purchase_return', 1, 120], ['buy', 10, 120], ['buy', 5, 120]], {'cogs': 360, 'revenue': 600, 'inventory': 2520, 'layers': [[21, 120]], 'rejected': [1, 3]}], ['control 6', [['sell', 12, 250], ['sell', 12, 200], ['buy', 5, 100], ['sell', 12, 250], ['sell', 12, 200], ['purchase_return', 1, 100], ['sell', 3, 250]], {'cogs': 300, 'revenue': 750, 'inventory': 100, 'layers': [[1, 100]], 'rejected': [0, 1, 3, 4]}]], [['regression: consumption order', [['buy', 10, 150], ['sell', 3, 250], ['sell', 12, 200], ['buy', 5, 120], ['sell', 3, 200], ['buy', 1, 100], ['sell', 1, 250], ['buy', 2, 100], ['sell', 12, 200], ['buy', 10, 100]], {'cogs': 1050, 'revenue': 1600, 'inventory': 2350, 'layers': [[3, 150], [5, 120], [13, 100]], 'rejected': [2, 8]}], ['control 1', [['sell', 12, 200], ['sell', 6, 250], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2]}], ['control 2', [['buy', 10, 100], ['sell', 12, 250], ['sell', 2, 250], ['sell', 12, 200], ['sell', 6, 200], ['buy', 1, 150], ['buy', 2, 120]], {'cogs': 800, 'revenue': 1700, 'inventory': 590, 'layers': [[2, 100], [1, 150], [2, 120]], 'rejected': [1, 3]}], ['control 3', [['purchase_return', 2, 100], ['sell', 12, 250], ['buy', 10, 100], ['buy', 1, 100], ['sell', 6, 200]], {'cogs': 600, 'revenue': 1200, 'inventory': 500, 'layers': [[5, 100]], 'rejected': [0, 1]}], ['control 4', [['sell', 12, 200], ['buy', 10, 100], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1240, 'layers': [[10, 100], [2, 120]], 'rejected': [0]}], ['control 5', [['purchase_return', 5, 100], ['sell', 2, 200], ['purchase_return', 5, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2]}], ['control 6', [['purchase_return', 2, 120], ['sell', 1, 250], ['purchase_return', 1, 120], ['purchase_return', 1, 120], ['buy', 10, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1200, 'layers': [[10, 120]], 'rejected': [0, 1, 2, 3]}]], [['regression: consumption order', [['purchase_return', 1, 100], ['buy', 2, 150], ['sell', 6, 200], ['sell', 2, 250], ['buy', 5, 120], ['buy', 5, 150], ['sell', 1, 250], ['purchase_return', 2, 100]], {'cogs': 420, 'revenue': 750, 'inventory': 1230, 'layers': [[4, 120], [5, 150]], 'rejected': [0, 2, 7]}], ['regression: consumption order, partial-repair probe', [['buy', 2, 120], ['purchase_return', 1, 150], ['buy', 1, 100], ['buy', 5, 100], ['sell', 3, 200]], {'cogs': 340, 'revenue': 600, 'inventory': 500, 'layers': [[5, 100]], 'rejected': [1]}], ['control 1', [['purchase_return', 5, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 320, 'layers': [[2, 100], [1, 120]], 'rejected': [0, 1]}], ['control 2', [['sell', 1, 250], ['buy', 5, 100], ['buy', 10, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 10, 100], ['sell', 6, 200], ['buy', 1, 120], ['buy', 10, 150], ['buy', 10, 150]], {'cogs': 800, 'revenue': 1700, 'inventory': 5020, 'layers': [[19, 100], [1, 120], [20, 150]], 'rejected': [0]}], ['control 3', [['purchase_return', 1, 100], ['sell', 1, 200], ['sell', 1, 250], ['sell', 3, 200], ['sell', 6, 200], ['buy', 10, 120], ['buy', 2, 150], ['buy', 2, 100], ['purchase_return', 2, 150]], {'cogs': 0, 'revenue': 0, 'inventory': 1400, 'layers': [[10, 120], [2, 100]], 'rejected': [0, 1, 2, 3, 4]}], ['control 4', [['buy', 1, 100], ['purchase_return', 5, 100], ['sell', 3, 200], ['buy', 1, 150], ['buy', 1, 150], ['sell', 3, 200], ['buy', 2, 120], ['buy', 10, 120]], {'cogs': 400, 'revenue': 600, 'inventory': 1440, 'layers': [[12, 120]], 'rejected': [1, 2]}], ['control 5', [['sell', 6, 200], ['sell', 12, 200], ['sell', 2, 200], ['sell', 2, 200], ['buy', 2, 100], ['purchase_return', 1, 120], ['buy', 2, 150], ['sell', 2, 200], ['sell', 2, 200], ['sell', 2, 200]], {'cogs': 500, 'revenue': 800, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 5, 9]}]], [['regression: consumption order', [['sell', 1, 250], ['sell', 3, 200], ['purchase_return', 1, 100], ['buy', 2, 120], ['buy', 5, 150], ['sell', 3, 200], ['sell', 1, 200], ['sell', 6, 250], ['buy', 2, 120]], {'cogs': 540, 'revenue': 800, 'inventory': 690, 'layers': [[3, 150], [2, 120]], 'rejected': [0, 1, 2, 7]}], ['regression: consumption order, partial-repair probe', [['buy', 2, 150], ['buy', 10, 120], ['sell', 1, 200], ['purchase_return', 5, 100], ['buy', 1, 100], ['buy', 2, 150], ['buy', 1, 100], ['buy', 5, 100], ['sell', 3, 200]], {'cogs': 540, 'revenue': 800, 'inventory': 1960, 'layers': [[8, 120], [1, 100], [2, 150], [6, 100]], 'rejected': [3]}], ['control 1', [['buy', 1, 100], ['purchase_return', 2, 150], ['purchase_return', 1, 120], ['purchase_return', 2, 100], ['buy', 5, 100], ['buy', 10, 100], ['buy', 1, 150], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1870, 'layers': [[16, 100], [1, 150], [1, 120]], 'rejected': [1, 2, 3]}], ['control 2', [['sell', 3, 250], ['purchase_return', 1, 150], ['purchase_return', 2, 120], ['sell', 6, 200], ['purchase_return', 2, 100]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4]}], ['control 3', [['sell', 6, 250], ['sell', 2, 250], ['sell', 3, 250], ['sell', 12, 250], ['sell', 12, 250], ['sell', 3, 250], ['buy', 1, 100], ['buy', 5, 120], ['buy', 5, 150], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1690, 'layers': [[1, 100], [5, 120], [5, 150], [2, 120]], 'rejected': [0, 1, 2, 3, 4, 5]}], ['control 4', [['sell', 6, 200], ['purchase_return', 1, 150], ['buy', 5, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 600, 'layers': [[5, 120]], 'rejected': [0, 1]}], ['control 5', [['sell', 3, 200], ['purchase_return', 5, 150], ['buy', 10, 100], ['sell', 1, 200], ['buy', 5, 120], ['buy', 5, 120], ['buy', 2, 150]], {'cogs': 100, 'revenue': 200, 'inventory': 2400, 'layers': [[9, 100], [10, 120], [2, 150]], 'rejected': [0, 1]}]], [['regression: consumption order', [['buy', 10, 100], ['buy', 10, 150], ['purchase_return', 5, 100], ['sell', 6, 200], ['sell', 3, 200], ['sell', 2, 200]], {'cogs': 1400, 'revenue': 2200, 'inventory': 600, 'layers': [[4, 150]], 'rejected': []}], ['regression: consumption order, partial-repair probe', [['buy', 5, 100], ['sell', 2, 200], ['sell', 3, 250], ['buy', 5, 120], ['buy', 10, 150], ['buy', 10, 100], ['sell', 2, 200], ['purchase_return', 2, 100], ['purchase_return', 1, 100]], {'cogs': 740, 'revenue': 1550, 'inventory': 2560, 'layers': [[3, 120], [10, 150], [7, 100]], 'rejected': []}], ['control 1', [['purchase_return', 2, 100], ['sell', 1, 200], ['buy', 5, 100], ['buy', 5, 100], ['purchase_return', 1, 150], ['sell', 2, 250], ['buy', 1, 100], ['sell', 1, 200]], {'cogs': 300, 'revenue': 700, 'inventory': 800, 'layers': [[8, 100]], 'rejected': [0, 1, 4]}], ['control 2', [['purchase_return', 1, 100], ['buy', 1, 100], ['sell', 3, 200], ['buy', 10, 100], ['buy', 5, 100], ['sell', 2, 200], ['purchase_return', 2, 150]], {'cogs': 200, 'revenue': 400, 'inventory': 1400, 'layers': [[14, 100]], 'rejected': [0, 2, 6]}], ['control 3', [['buy', 10, 120], ['buy', 1, 120], ['purchase_return', 2, 150], ['sell', 2, 250], ['buy', 1, 100]], {'cogs': 240, 'revenue': 500, 'inventory': 1180, 'layers': [[9, 120], [1, 100]], 'rejected': [2]}], ['control 4', [['sell', 6, 250], ['purchase_return', 2, 100], ['sell', 12, 250], ['sell', 3, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3]}], ['control 5', [['sell', 6, 250], ['sell', 3, 250], ['sell', 12, 200], ['sell', 1, 250], ['sell', 3, 250], ['purchase_return', 5, 150], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4, 5, 6]}]]]
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):
    layers = []
    cogs = revenue = 0
    short = []
    for i, ev in enumerate(x):
        if ev[0] == 'buy':
            if layers and layers[-1][1] == ev[2]:
                layers[-1][0] += ev[1]
            else:
                layers.append([ev[1], ev[2]])
        elif ev[0] == 'sell':
            qty = ev[1]
            if qty > sum(l[0] for l in layers):
                short.append(i)
                continue
            revenue += qty * ev[2]
            while qty:
                head = min(layers, key=lambda l: l[1])
                take = min(qty, head[0])
                cogs += take * head[1]
                head[0] -= take
                qty -= take
                if head[0] == 0:
                    layers.remove(head)
        elif ev[0] == 'purchase_return':
            match = [l for l in layers if l[1] == ev[2] and l[0] >= ev[1]]
            if not match:
                short.append(i)
                continue
            match[-1][0] -= ev[1]
            if match[-1][0] == 0:
                layers.remove(match[-1])
    inventory = sum(q * c for q, c in layers)
    return {'cogs': cogs, 'revenue': revenue, 'inventory': inventory, 'layers': layers, 'rejected': short}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: consumption order', [['buy', 5, 120], ['sell', 6, 200], ['sell', 3, 200], ['buy', 1, 100], ['buy', 5, 120], ['buy', 5, 100], ['sell', 6, 200], ['sell', 12, 250]], {'cogs': 1060, 'revenue': 1800, 'inventory': 740, 'layers': [[2, 120], [5, 100]], 'rejected': [1, 7]}], ['control 1', [['sell', 3, 250], ['buy', 2, 120], ['purchase_return', 1, 100], ['buy', 5, 100], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 980, 'layers': [[2, 120], [5, 100], [2, 120]], 'rejected': [0, 2]}], ['control 2', [['buy', 5, 150], ['sell', 3, 250], ['sell', 2, 250], ['buy', 10, 100], ['buy', 10, 120], ['purchase_return', 2, 100], ['purchase_return', 5, 100], ['buy', 10, 150], ['buy', 2, 120], ['purchase_return', 5, 100]], {'cogs': 750, 'revenue': 1250, 'inventory': 3240, 'layers': [[3, 100], [10, 120], [10, 150], [2, 120]], 'rejected': [9]}], ['control 3', [['buy', 1, 120], ['sell', 12, 200], ['sell', 2, 250], ['sell', 2, 250]], {'cogs': 0, 'revenue': 0, 'inventory': 120, 'layers': [[1, 120]], 'rejected': [1, 2, 3]}], ['control 4', [['buy', 5, 100], ['sell', 3, 250], ['sell', 12, 200]], {'cogs': 300, 'revenue': 750, 'inventory': 200, 'layers': [[2, 100]], 'rejected': [2]}], ['control 5', [['buy', 10, 120], ['purchase_return', 1, 100], ['sell', 1, 200], ['purchase_return', 2, 100], ['sell', 2, 200], ['purchase_return', 1, 120], ['buy', 10, 120], ['buy', 5, 120]], {'cogs': 360, 'revenue': 600, 'inventory': 2520, 'layers': [[21, 120]], 'rejected': [1, 3]}], ['control 6', [['sell', 12, 250], ['sell', 12, 200], ['buy', 5, 100], ['sell', 12, 250], ['sell', 12, 200], ['purchase_return', 1, 100], ['sell', 3, 250]], {'cogs': 300, 'revenue': 750, 'inventory': 100, 'layers': [[1, 100]], 'rejected': [0, 1, 3, 4]}]], [['regression: consumption order', [['buy', 10, 150], ['sell', 3, 250], ['sell', 12, 200], ['buy', 5, 120], ['sell', 3, 200], ['buy', 1, 100], ['sell', 1, 250], ['buy', 2, 100], ['sell', 12, 200], ['buy', 10, 100]], {'cogs': 1050, 'revenue': 1600, 'inventory': 2350, 'layers': [[3, 150], [5, 120], [13, 100]], 'rejected': [2, 8]}], ['control 1', [['sell', 12, 200], ['sell', 6, 250], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2]}], ['control 2', [['buy', 10, 100], ['sell', 12, 250], ['sell', 2, 250], ['sell', 12, 200], ['sell', 6, 200], ['buy', 1, 150], ['buy', 2, 120]], {'cogs': 800, 'revenue': 1700, 'inventory': 590, 'layers': [[2, 100], [1, 150], [2, 120]], 'rejected': [1, 3]}], ['control 3', [['purchase_return', 2, 100], ['sell', 12, 250], ['buy', 10, 100], ['buy', 1, 100], ['sell', 6, 200]], {'cogs': 600, 'revenue': 1200, 'inventory': 500, 'layers': [[5, 100]], 'rejected': [0, 1]}], ['control 4', [['sell', 12, 200], ['buy', 10, 100], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1240, 'layers': [[10, 100], [2, 120]], 'rejected': [0]}], ['control 5', [['purchase_return', 5, 100], ['sell', 2, 200], ['purchase_return', 5, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2]}], ['control 6', [['purchase_return', 2, 120], ['sell', 1, 250], ['purchase_return', 1, 120], ['purchase_return', 1, 120], ['buy', 10, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1200, 'layers': [[10, 120]], 'rejected': [0, 1, 2, 3]}]], [['regression: consumption order', [['purchase_return', 1, 100], ['buy', 2, 150], ['sell', 6, 200], ['sell', 2, 250], ['buy', 5, 120], ['buy', 5, 150], ['sell', 1, 250], ['purchase_return', 2, 100]], {'cogs': 420, 'revenue': 750, 'inventory': 1230, 'layers': [[4, 120], [5, 150]], 'rejected': [0, 2, 7]}], ['regression: consumption order, partial-repair probe', [['buy', 2, 120], ['purchase_return', 1, 150], ['buy', 1, 100], ['buy', 5, 100], ['sell', 3, 200]], {'cogs': 340, 'revenue': 600, 'inventory': 500, 'layers': [[5, 100]], 'rejected': [1]}], ['control 1', [['purchase_return', 5, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 320, 'layers': [[2, 100], [1, 120]], 'rejected': [0, 1]}], ['control 2', [['sell', 1, 250], ['buy', 5, 100], ['buy', 10, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 10, 100], ['sell', 6, 200], ['buy', 1, 120], ['buy', 10, 150], ['buy', 10, 150]], {'cogs': 800, 'revenue': 1700, 'inventory': 5020, 'layers': [[19, 100], [1, 120], [20, 150]], 'rejected': [0]}], ['control 3', [['purchase_return', 1, 100], ['sell', 1, 200], ['sell', 1, 250], ['sell', 3, 200], ['sell', 6, 200], ['buy', 10, 120], ['buy', 2, 150], ['buy', 2, 100], ['purchase_return', 2, 150]], {'cogs': 0, 'revenue': 0, 'inventory': 1400, 'layers': [[10, 120], [2, 100]], 'rejected': [0, 1, 2, 3, 4]}], ['control 4', [['buy', 1, 100], ['purchase_return', 5, 100], ['sell', 3, 200], ['buy', 1, 150], ['buy', 1, 150], ['sell', 3, 200], ['buy', 2, 120], ['buy', 10, 120]], {'cogs': 400, 'revenue': 600, 'inventory': 1440, 'layers': [[12, 120]], 'rejected': [1, 2]}], ['control 5', [['sell', 6, 200], ['sell', 12, 200], ['sell', 2, 200], ['sell', 2, 200], ['buy', 2, 100], ['purchase_return', 1, 120], ['buy', 2, 150], ['sell', 2, 200], ['sell', 2, 200], ['sell', 2, 200]], {'cogs': 500, 'revenue': 800, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 5, 9]}]], [['regression: consumption order', [['sell', 1, 250], ['sell', 3, 200], ['purchase_return', 1, 100], ['buy', 2, 120], ['buy', 5, 150], ['sell', 3, 200], ['sell', 1, 200], ['sell', 6, 250], ['buy', 2, 120]], {'cogs': 540, 'revenue': 800, 'inventory': 690, 'layers': [[3, 150], [2, 120]], 'rejected': [0, 1, 2, 7]}], ['regression: consumption order, partial-repair probe', [['buy', 2, 150], ['buy', 10, 120], ['sell', 1, 200], ['purchase_return', 5, 100], ['buy', 1, 100], ['buy', 2, 150], ['buy', 1, 100], ['buy', 5, 100], ['sell', 3, 200]], {'cogs': 540, 'revenue': 800, 'inventory': 1960, 'layers': [[8, 120], [1, 100], [2, 150], [6, 100]], 'rejected': [3]}], ['control 1', [['buy', 1, 100], ['purchase_return', 2, 150], ['purchase_return', 1, 120], ['purchase_return', 2, 100], ['buy', 5, 100], ['buy', 10, 100], ['buy', 1, 150], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1870, 'layers': [[16, 100], [1, 150], [1, 120]], 'rejected': [1, 2, 3]}], ['control 2', [['sell', 3, 250], ['purchase_return', 1, 150], ['purchase_return', 2, 120], ['sell', 6, 200], ['purchase_return', 2, 100]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4]}], ['control 3', [['sell', 6, 250], ['sell', 2, 250], ['sell', 3, 250], ['sell', 12, 250], ['sell', 12, 250], ['sell', 3, 250], ['buy', 1, 100], ['buy', 5, 120], ['buy', 5, 150], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1690, 'layers': [[1, 100], [5, 120], [5, 150], [2, 120]], 'rejected': [0, 1, 2, 3, 4, 5]}], ['control 4', [['sell', 6, 200], ['purchase_return', 1, 150], ['buy', 5, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 600, 'layers': [[5, 120]], 'rejected': [0, 1]}], ['control 5', [['sell', 3, 200], ['purchase_return', 5, 150], ['buy', 10, 100], ['sell', 1, 200], ['buy', 5, 120], ['buy', 5, 120], ['buy', 2, 150]], {'cogs': 100, 'revenue': 200, 'inventory': 2400, 'layers': [[9, 100], [10, 120], [2, 150]], 'rejected': [0, 1]}]], [['regression: consumption order', [['buy', 10, 100], ['buy', 10, 150], ['purchase_return', 5, 100], ['sell', 6, 200], ['sell', 3, 200], ['sell', 2, 200]], {'cogs': 1400, 'revenue': 2200, 'inventory': 600, 'layers': [[4, 150]], 'rejected': []}], ['regression: consumption order, partial-repair probe', [['buy', 5, 100], ['sell', 2, 200], ['sell', 3, 250], ['buy', 5, 120], ['buy', 10, 150], ['buy', 10, 100], ['sell', 2, 200], ['purchase_return', 2, 100], ['purchase_return', 1, 100]], {'cogs': 740, 'revenue': 1550, 'inventory': 2560, 'layers': [[3, 120], [10, 150], [7, 100]], 'rejected': []}], ['control 1', [['purchase_return', 2, 100], ['sell', 1, 200], ['buy', 5, 100], ['buy', 5, 100], ['purchase_return', 1, 150], ['sell', 2, 250], ['buy', 1, 100], ['sell', 1, 200]], {'cogs': 300, 'revenue': 700, 'inventory': 800, 'layers': [[8, 100]], 'rejected': [0, 1, 4]}], ['control 2', [['purchase_return', 1, 100], ['buy', 1, 100], ['sell', 3, 200], ['buy', 10, 100], ['buy', 5, 100], ['sell', 2, 200], ['purchase_return', 2, 150]], {'cogs': 200, 'revenue': 400, 'inventory': 1400, 'layers': [[14, 100]], 'rejected': [0, 2, 6]}], ['control 3', [['buy', 10, 120], ['buy', 1, 120], ['purchase_return', 2, 150], ['sell', 2, 250], ['buy', 1, 100]], {'cogs': 240, 'revenue': 500, 'inventory': 1180, 'layers': [[9, 120], [1, 100]], 'rejected': [2]}], ['control 4', [['sell', 6, 250], ['purchase_return', 2, 100], ['sell', 12, 250], ['sell', 3, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3]}], ['control 5', [['sell', 6, 250], ['sell', 3, 250], ['sell', 12, 200], ['sell', 1, 250], ['sell', 3, 250], ['purchase_return', 5, 150], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4, 5, 6]}]]]
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:
Cost of goods sold uses the newest purchase prices.

x = [['buy', qty, unit_cost] | ['sell', qty, unit_price] | ['purchase_return', qty, unit_cost]]. Layers are kept oldest first; a buy at the same cost as the newest layer merges into it. A sale consumes layers oldest first (COGS) and records revenue; a sale exceeding on-hand quantity is rejected whole. A purchase return removes qty from the newest layer at that cost holding at least qty, else it is rejected. Emptied layers are removed. Return {'cogs', 'revenue', 'inventory': sum qty*cost, 'layers', 'rejected': event indexes}.

split: open-access


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

N = 1
observations = []
def solve(x):
    layers = []
    cogs = revenue = 0
    short = []
    for i, ev in enumerate(x):
        if ev[0] == 'buy':
            if layers and layers[0][1] == ev[2]:
                layers[-1][0] += ev[1]
            else:
                layers.append([ev[1], ev[2]])
        elif ev[0] == 'sell':
            qty = ev[1]
            if qty > sum(l[0] for l in layers):
                short.append(i)
                continue
            revenue += qty * ev[2]
            while qty:
                head = layers[0]
                take = min(qty, head[0])
                cogs += take * head[1]
                head[0] -= take
                qty -= take
                if head[0] == 0:
                    layers.pop(0)
        elif ev[0] == 'purchase_return':
            match = [l for l in layers if l[1] == ev[2] and l[0] >= ev[1]]
            if not match:
                short.append(i)
                continue
            match[-1][0] -= ev[1]
            if match[-1][0] == 0:
                layers.remove(match[-1])
    inventory = sum(q * c for q, c in layers)
    return {'cogs': cogs, 'revenue': revenue, 'inventory': inventory, 'layers': layers, 'rejected': short}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: layer merge target', [['sell', 3, 250], ['buy', 2, 120], ['purchase_return', 1, 100], ['buy', 5, 100], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 980, 'layers': [[2, 120], [5, 100], [2, 120]], 'rejected': [0, 2]}], ['control 1', [['buy', 5, 150], ['sell', 3, 250], ['sell', 2, 250], ['buy', 10, 100], ['buy', 10, 120], ['purchase_return', 2, 100], ['purchase_return', 5, 100], ['buy', 10, 150], ['buy', 2, 120], ['purchase_return', 5, 100]], {'cogs': 750, 'revenue': 1250, 'inventory': 3240, 'layers': [[3, 100], [10, 120], [10, 150], [2, 120]], 'rejected': [9]}], ['control 2', [['buy', 1, 120], ['sell', 12, 200], ['sell', 2, 250], ['sell', 2, 250]], {'cogs': 0, 'revenue': 0, 'inventory': 120, 'layers': [[1, 120]], 'rejected': [1, 2, 3]}], ['control 3', [['buy', 5, 100], ['sell', 3, 250], ['sell', 12, 200]], {'cogs': 300, 'revenue': 750, 'inventory': 200, 'layers': [[2, 100]], 'rejected': [2]}], ['control 4', [['buy', 10, 120], ['purchase_return', 1, 100], ['sell', 1, 200], ['purchase_return', 2, 100], ['sell', 2, 200], ['purchase_return', 1, 120], ['buy', 10, 120], ['buy', 5, 120]], {'cogs': 360, 'revenue': 600, 'inventory': 2520, 'layers': [[21, 120]], 'rejected': [1, 3]}], ['control 5', [['sell', 12, 250], ['sell', 12, 200], ['buy', 5, 100], ['sell', 12, 250], ['sell', 12, 200], ['purchase_return', 1, 100], ['sell', 3, 250]], {'cogs': 300, 'revenue': 750, 'inventory': 100, 'layers': [[1, 100]], 'rejected': [0, 1, 3, 4]}], ['control 6', [['buy', 5, 100], ['sell', 3, 250], ['buy', 5, 100]], {'cogs': 300, 'revenue': 750, 'inventory': 700, 'layers': [[7, 100]], 'rejected': []}]], [['regression: layer merge target', [['buy', 10, 150], ['sell', 3, 250], ['sell', 12, 200], ['buy', 5, 120], ['sell', 3, 200], ['buy', 1, 100], ['sell', 1, 250], ['buy', 2, 100], ['sell', 12, 200], ['buy', 10, 100]], {'cogs': 1050, 'revenue': 1600, 'inventory': 2350, 'layers': [[3, 150], [5, 120], [13, 100]], 'rejected': [2, 8]}], ['regression: layer merge target, partial-repair probe', [['sell', 2, 250], ['purchase_return', 1, 150], ['buy', 10, 100], ['buy', 10, 150], ['buy', 2, 150], ['buy', 2, 100], ['sell', 2, 250], ['sell', 3, 250], ['buy', 5, 120]], {'cogs': 500, 'revenue': 1250, 'inventory': 3100, 'layers': [[5, 100], [12, 150], [2, 100], [5, 120]], 'rejected': [0, 1]}], ['control 1', [['sell', 12, 200], ['sell', 6, 250], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2]}], ['control 2', [['buy', 10, 100], ['sell', 12, 250], ['sell', 2, 250], ['sell', 12, 200], ['sell', 6, 200], ['buy', 1, 150], ['buy', 2, 120]], {'cogs': 800, 'revenue': 1700, 'inventory': 590, 'layers': [[2, 100], [1, 150], [2, 120]], 'rejected': [1, 3]}], ['control 3', [['purchase_return', 2, 100], ['sell', 12, 250], ['buy', 10, 100], ['buy', 1, 100], ['sell', 6, 200]], {'cogs': 600, 'revenue': 1200, 'inventory': 500, 'layers': [[5, 100]], 'rejected': [0, 1]}], ['control 4', [['buy', 10, 120], ['sell', 1, 200], ['buy', 10, 120], ['buy', 2, 120], ['sell', 6, 250], ['buy', 1, 100], ['buy', 2, 150], ['sell', 1, 250]], {'cogs': 960, 'revenue': 1950, 'inventory': 2080, 'layers': [[14, 120], [1, 100], [2, 150]], 'rejected': []}], ['control 5', [['sell', 12, 200], ['buy', 10, 100], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1240, 'layers': [[10, 100], [2, 120]], 'rejected': [0]}]], [['regression: layer merge target', [['sell', 1, 250], ['buy', 5, 100], ['buy', 10, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 10, 100], ['sell', 6, 200], ['buy', 1, 120], ['buy', 10, 150], ['buy', 10, 150]], {'cogs': 800, 'revenue': 1700, 'inventory': 5020, 'layers': [[19, 100], [1, 120], [20, 150]], 'rejected': [0]}], ['regression: layer merge target, partial-repair probe', [['purchase_return', 2, 100], ['buy', 10, 150], ['buy', 1, 120], ['purchase_return', 2, 100], ['sell', 6, 200], ['purchase_return', 1, 100], ['buy', 10, 100], ['sell', 3, 250], ['buy', 2, 120], ['sell', 2, 200]], {'cogs': 1620, 'revenue': 2350, 'inventory': 1240, 'layers': [[10, 100], [2, 120]], 'rejected': [0, 3, 5]}], ['control 1', [['purchase_return', 5, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 320, 'layers': [[2, 100], [1, 120]], 'rejected': [0, 1]}], ['control 2', [['purchase_return', 1, 100], ['sell', 1, 200], ['sell', 1, 250], ['sell', 3, 200], ['sell', 6, 200], ['buy', 10, 120], ['buy', 2, 150], ['buy', 2, 100], ['purchase_return', 2, 150]], {'cogs': 0, 'revenue': 0, 'inventory': 1400, 'layers': [[10, 120], [2, 100]], 'rejected': [0, 1, 2, 3, 4]}], ['control 3', [['buy', 1, 100], ['purchase_return', 5, 100], ['sell', 3, 200], ['buy', 1, 150], ['buy', 1, 150], ['sell', 3, 200], ['buy', 2, 120], ['buy', 10, 120]], {'cogs': 400, 'revenue': 600, 'inventory': 1440, 'layers': [[12, 120]], 'rejected': [1, 2]}], ['control 4', [['purchase_return', 1, 100], ['buy', 2, 150], ['sell', 6, 200], ['sell', 2, 250], ['buy', 5, 120], ['buy', 5, 150], ['sell', 1, 250], ['purchase_return', 2, 100]], {'cogs': 420, 'revenue': 750, 'inventory': 1230, 'layers': [[4, 120], [5, 150]], 'rejected': [0, 2, 7]}], ['control 5', [['buy', 2, 120], ['purchase_return', 1, 150], ['buy', 1, 100], ['buy', 5, 100], ['sell', 3, 200]], {'cogs': 340, 'revenue': 600, 'inventory': 500, 'layers': [[5, 100]], 'rejected': [1]}]], [['regression: layer merge target', [['buy', 2, 150], ['buy', 10, 120], ['sell', 1, 200], ['purchase_return', 5, 100], ['buy', 1, 100], ['buy', 2, 150], ['buy', 1, 100], ['buy', 5, 100], ['sell', 3, 200]], {'cogs': 540, 'revenue': 800, 'inventory': 1960, 'layers': [[8, 120], [1, 100], [2, 150], [6, 100]], 'rejected': [3]}], ['control 1', [['sell', 1, 250], ['sell', 3, 200], ['purchase_return', 1, 100], ['buy', 2, 120], ['buy', 5, 150], ['sell', 3, 200], ['sell', 1, 200], ['sell', 6, 250], ['buy', 2, 120]], {'cogs': 540, 'revenue': 800, 'inventory': 690, 'layers': [[3, 150], [2, 120]], 'rejected': [0, 1, 2, 7]}], ['control 2', [['buy', 1, 100], ['purchase_return', 2, 150], ['purchase_return', 1, 120], ['purchase_return', 2, 100], ['buy', 5, 100], ['buy', 10, 100], ['buy', 1, 150], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1870, 'layers': [[16, 100], [1, 150], [1, 120]], 'rejected': [1, 2, 3]}], ['control 3', [['buy', 1, 100], ['buy', 2, 120], ['buy', 2, 120], ['sell', 3, 200], ['sell', 12, 200], ['buy', 5, 120], ['sell', 3, 200], ['purchase_return', 1, 100], ['buy', 2, 100]], {'cogs': 700, 'revenue': 1200, 'inventory': 680, 'layers': [[4, 120], [2, 100]], 'rejected': [4, 7]}], ['control 4', [['sell', 3, 250], ['purchase_return', 1, 150], ['purchase_return', 2, 120], ['sell', 6, 200], ['purchase_return', 2, 100]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4]}], ['control 5', [['sell', 6, 250], ['sell', 2, 250], ['sell', 3, 250], ['sell', 12, 250], ['sell', 12, 250], ['sell', 3, 250], ['buy', 1, 100], ['buy', 5, 120], ['buy', 5, 150], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1690, 'layers': [[1, 100], [5, 120], [5, 150], [2, 120]], 'rejected': [0, 1, 2, 3, 4, 5]}], ['control 6', [['sell', 6, 200], ['purchase_return', 1, 150], ['buy', 5, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 600, 'layers': [[5, 120]], 'rejected': [0, 1]}]], [['regression: layer merge target', [['buy', 2, 150], ['buy', 2, 100], ['buy', 2, 150]], {'cogs': 0, 'revenue': 0, 'inventory': 800, 'layers': [[2, 150], [2, 100], [2, 150]], 'rejected': []}], ['control 1', [['buy', 10, 100], ['buy', 10, 150], ['purchase_return', 5, 100], ['sell', 6, 200], ['sell', 3, 200], ['sell', 2, 200]], {'cogs': 1400, 'revenue': 2200, 'inventory': 600, 'layers': [[4, 150]], 'rejected': []}], ['control 2', [['purchase_return', 2, 100], ['sell', 1, 200], ['buy', 5, 100], ['buy', 5, 100], ['purchase_return', 1, 150], ['sell', 2, 250], ['buy', 1, 100], ['sell', 1, 200]], {'cogs': 300, 'revenue': 700, 'inventory': 800, 'layers': [[8, 100]], 'rejected': [0, 1, 4]}], ['control 3', [['purchase_return', 1, 100], ['buy', 1, 100], ['sell', 3, 200], ['buy', 10, 100], ['buy', 5, 100], ['sell', 2, 200], ['purchase_return', 2, 150]], {'cogs': 200, 'revenue': 400, 'inventory': 1400, 'layers': [[14, 100]], 'rejected': [0, 2, 6]}], ['control 4', [['buy', 10, 120], ['buy', 1, 120], ['purchase_return', 2, 150], ['sell', 2, 250], ['buy', 1, 100]], {'cogs': 240, 'revenue': 500, 'inventory': 1180, 'layers': [[9, 120], [1, 100]], 'rejected': [2]}], ['control 5', [['sell', 6, 250], ['purchase_return', 2, 100], ['sell', 12, 250], ['sell', 3, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3]}], ['control 6', [['sell', 6, 250], ['sell', 3, 250], ['sell', 12, 200], ['sell', 1, 250], ['sell', 3, 250], ['purchase_return', 5, 150], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4, 5, 6]}]]]
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):
    layers = []
    cogs = revenue = 0
    short = []
    for i, ev in enumerate(x):
        if ev[0] == 'buy':
            if any(l[1] == ev[2] for l in layers):
                layers[-1][0] += ev[1]
            else:
                layers.append([ev[1], ev[2]])
        elif ev[0] == 'sell':
            qty = ev[1]
            if qty > sum(l[0] for l in layers):
                short.append(i)
                continue
            revenue += qty * ev[2]
            while qty:
                head = layers[0]
                take = min(qty, head[0])
                cogs += take * head[1]
                head[0] -= take
                qty -= take
                if head[0] == 0:
                    layers.pop(0)
        elif ev[0] == 'purchase_return':
            match = [l for l in layers if l[1] == ev[2] and l[0] >= ev[1]]
            if not match:
                short.append(i)
                continue
            match[-1][0] -= ev[1]
            if match[-1][0] == 0:
                layers.remove(match[-1])
    inventory = sum(q * c for q, c in layers)
    return {'cogs': cogs, 'revenue': revenue, 'inventory': inventory, 'layers': layers, 'rejected': short}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: layer merge target', [['sell', 3, 250], ['buy', 2, 120], ['purchase_return', 1, 100], ['buy', 5, 100], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 980, 'layers': [[2, 120], [5, 100], [2, 120]], 'rejected': [0, 2]}], ['control 1', [['buy', 5, 150], ['sell', 3, 250], ['sell', 2, 250], ['buy', 10, 100], ['buy', 10, 120], ['purchase_return', 2, 100], ['purchase_return', 5, 100], ['buy', 10, 150], ['buy', 2, 120], ['purchase_return', 5, 100]], {'cogs': 750, 'revenue': 1250, 'inventory': 3240, 'layers': [[3, 100], [10, 120], [10, 150], [2, 120]], 'rejected': [9]}], ['control 2', [['buy', 1, 120], ['sell', 12, 200], ['sell', 2, 250], ['sell', 2, 250]], {'cogs': 0, 'revenue': 0, 'inventory': 120, 'layers': [[1, 120]], 'rejected': [1, 2, 3]}], ['control 3', [['buy', 5, 100], ['sell', 3, 250], ['sell', 12, 200]], {'cogs': 300, 'revenue': 750, 'inventory': 200, 'layers': [[2, 100]], 'rejected': [2]}], ['control 4', [['buy', 10, 120], ['purchase_return', 1, 100], ['sell', 1, 200], ['purchase_return', 2, 100], ['sell', 2, 200], ['purchase_return', 1, 120], ['buy', 10, 120], ['buy', 5, 120]], {'cogs': 360, 'revenue': 600, 'inventory': 2520, 'layers': [[21, 120]], 'rejected': [1, 3]}], ['control 5', [['sell', 12, 250], ['sell', 12, 200], ['buy', 5, 100], ['sell', 12, 250], ['sell', 12, 200], ['purchase_return', 1, 100], ['sell', 3, 250]], {'cogs': 300, 'revenue': 750, 'inventory': 100, 'layers': [[1, 100]], 'rejected': [0, 1, 3, 4]}], ['control 6', [['buy', 5, 100], ['sell', 3, 250], ['buy', 5, 100]], {'cogs': 300, 'revenue': 750, 'inventory': 700, 'layers': [[7, 100]], 'rejected': []}]], [['regression: layer merge target', [['buy', 10, 150], ['sell', 3, 250], ['sell', 12, 200], ['buy', 5, 120], ['sell', 3, 200], ['buy', 1, 100], ['sell', 1, 250], ['buy', 2, 100], ['sell', 12, 200], ['buy', 10, 100]], {'cogs': 1050, 'revenue': 1600, 'inventory': 2350, 'layers': [[3, 150], [5, 120], [13, 100]], 'rejected': [2, 8]}], ['regression: layer merge target, partial-repair probe', [['sell', 2, 250], ['purchase_return', 1, 150], ['buy', 10, 100], ['buy', 10, 150], ['buy', 2, 150], ['buy', 2, 100], ['sell', 2, 250], ['sell', 3, 250], ['buy', 5, 120]], {'cogs': 500, 'revenue': 1250, 'inventory': 3100, 'layers': [[5, 100], [12, 150], [2, 100], [5, 120]], 'rejected': [0, 1]}], ['control 1', [['sell', 12, 200], ['sell', 6, 250], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2]}], ['control 2', [['buy', 10, 100], ['sell', 12, 250], ['sell', 2, 250], ['sell', 12, 200], ['sell', 6, 200], ['buy', 1, 150], ['buy', 2, 120]], {'cogs': 800, 'revenue': 1700, 'inventory': 590, 'layers': [[2, 100], [1, 150], [2, 120]], 'rejected': [1, 3]}], ['control 3', [['purchase_return', 2, 100], ['sell', 12, 250], ['buy', 10, 100], ['buy', 1, 100], ['sell', 6, 200]], {'cogs': 600, 'revenue': 1200, 'inventory': 500, 'layers': [[5, 100]], 'rejected': [0, 1]}], ['control 4', [['buy', 10, 120], ['sell', 1, 200], ['buy', 10, 120], ['buy', 2, 120], ['sell', 6, 250], ['buy', 1, 100], ['buy', 2, 150], ['sell', 1, 250]], {'cogs': 960, 'revenue': 1950, 'inventory': 2080, 'layers': [[14, 120], [1, 100], [2, 150]], 'rejected': []}], ['control 5', [['sell', 12, 200], ['buy', 10, 100], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1240, 'layers': [[10, 100], [2, 120]], 'rejected': [0]}]], [['regression: layer merge target', [['sell', 1, 250], ['buy', 5, 100], ['buy', 10, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 10, 100], ['sell', 6, 200], ['buy', 1, 120], ['buy', 10, 150], ['buy', 10, 150]], {'cogs': 800, 'revenue': 1700, 'inventory': 5020, 'layers': [[19, 100], [1, 120], [20, 150]], 'rejected': [0]}], ['regression: layer merge target, partial-repair probe', [['purchase_return', 2, 100], ['buy', 10, 150], ['buy', 1, 120], ['purchase_return', 2, 100], ['sell', 6, 200], ['purchase_return', 1, 100], ['buy', 10, 100], ['sell', 3, 250], ['buy', 2, 120], ['sell', 2, 200]], {'cogs': 1620, 'revenue': 2350, 'inventory': 1240, 'layers': [[10, 100], [2, 120]], 'rejected': [0, 3, 5]}], ['control 1', [['purchase_return', 5, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 320, 'layers': [[2, 100], [1, 120]], 'rejected': [0, 1]}], ['control 2', [['purchase_return', 1, 100], ['sell', 1, 200], ['sell', 1, 250], ['sell', 3, 200], ['sell', 6, 200], ['buy', 10, 120], ['buy', 2, 150], ['buy', 2, 100], ['purchase_return', 2, 150]], {'cogs': 0, 'revenue': 0, 'inventory': 1400, 'layers': [[10, 120], [2, 100]], 'rejected': [0, 1, 2, 3, 4]}], ['control 3', [['buy', 1, 100], ['purchase_return', 5, 100], ['sell', 3, 200], ['buy', 1, 150], ['buy', 1, 150], ['sell', 3, 200], ['buy', 2, 120], ['buy', 10, 120]], {'cogs': 400, 'revenue': 600, 'inventory': 1440, 'layers': [[12, 120]], 'rejected': [1, 2]}], ['control 4', [['purchase_return', 1, 100], ['buy', 2, 150], ['sell', 6, 200], ['sell', 2, 250], ['buy', 5, 120], ['buy', 5, 150], ['sell', 1, 250], ['purchase_return', 2, 100]], {'cogs': 420, 'revenue': 750, 'inventory': 1230, 'layers': [[4, 120], [5, 150]], 'rejected': [0, 2, 7]}], ['control 5', [['buy', 2, 120], ['purchase_return', 1, 150], ['buy', 1, 100], ['buy', 5, 100], ['sell', 3, 200]], {'cogs': 340, 'revenue': 600, 'inventory': 500, 'layers': [[5, 100]], 'rejected': [1]}]], [['regression: layer merge target', [['buy', 2, 150], ['buy', 10, 120], ['sell', 1, 200], ['purchase_return', 5, 100], ['buy', 1, 100], ['buy', 2, 150], ['buy', 1, 100], ['buy', 5, 100], ['sell', 3, 200]], {'cogs': 540, 'revenue': 800, 'inventory': 1960, 'layers': [[8, 120], [1, 100], [2, 150], [6, 100]], 'rejected': [3]}], ['control 1', [['sell', 1, 250], ['sell', 3, 200], ['purchase_return', 1, 100], ['buy', 2, 120], ['buy', 5, 150], ['sell', 3, 200], ['sell', 1, 200], ['sell', 6, 250], ['buy', 2, 120]], {'cogs': 540, 'revenue': 800, 'inventory': 690, 'layers': [[3, 150], [2, 120]], 'rejected': [0, 1, 2, 7]}], ['control 2', [['buy', 1, 100], ['purchase_return', 2, 150], ['purchase_return', 1, 120], ['purchase_return', 2, 100], ['buy', 5, 100], ['buy', 10, 100], ['buy', 1, 150], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1870, 'layers': [[16, 100], [1, 150], [1, 120]], 'rejected': [1, 2, 3]}], ['control 3', [['buy', 1, 100], ['buy', 2, 120], ['buy', 2, 120], ['sell', 3, 200], ['sell', 12, 200], ['buy', 5, 120], ['sell', 3, 200], ['purchase_return', 1, 100], ['buy', 2, 100]], {'cogs': 700, 'revenue': 1200, 'inventory': 680, 'layers': [[4, 120], [2, 100]], 'rejected': [4, 7]}], ['control 4', [['sell', 3, 250], ['purchase_return', 1, 150], ['purchase_return', 2, 120], ['sell', 6, 200], ['purchase_return', 2, 100]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4]}], ['control 5', [['sell', 6, 250], ['sell', 2, 250], ['sell', 3, 250], ['sell', 12, 250], ['sell', 12, 250], ['sell', 3, 250], ['buy', 1, 100], ['buy', 5, 120], ['buy', 5, 150], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1690, 'layers': [[1, 100], [5, 120], [5, 150], [2, 120]], 'rejected': [0, 1, 2, 3, 4, 5]}], ['control 6', [['sell', 6, 200], ['purchase_return', 1, 150], ['buy', 5, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 600, 'layers': [[5, 120]], 'rejected': [0, 1]}]], [['regression: layer merge target', [['buy', 2, 150], ['buy', 2, 100], ['buy', 2, 150]], {'cogs': 0, 'revenue': 0, 'inventory': 800, 'layers': [[2, 150], [2, 100], [2, 150]], 'rejected': []}], ['control 1', [['buy', 10, 100], ['buy', 10, 150], ['purchase_return', 5, 100], ['sell', 6, 200], ['sell', 3, 200], ['sell', 2, 200]], {'cogs': 1400, 'revenue': 2200, 'inventory': 600, 'layers': [[4, 150]], 'rejected': []}], ['control 2', [['purchase_return', 2, 100], ['sell', 1, 200], ['buy', 5, 100], ['buy', 5, 100], ['purchase_return', 1, 150], ['sell', 2, 250], ['buy', 1, 100], ['sell', 1, 200]], {'cogs': 300, 'revenue': 700, 'inventory': 800, 'layers': [[8, 100]], 'rejected': [0, 1, 4]}], ['control 3', [['purchase_return', 1, 100], ['buy', 1, 100], ['sell', 3, 200], ['buy', 10, 100], ['buy', 5, 100], ['sell', 2, 200], ['purchase_return', 2, 150]], {'cogs': 200, 'revenue': 400, 'inventory': 1400, 'layers': [[14, 100]], 'rejected': [0, 2, 6]}], ['control 4', [['buy', 10, 120], ['buy', 1, 120], ['purchase_return', 2, 150], ['sell', 2, 250], ['buy', 1, 100]], {'cogs': 240, 'revenue': 500, 'inventory': 1180, 'layers': [[9, 120], [1, 100]], 'rejected': [2]}], ['control 5', [['sell', 6, 250], ['purchase_return', 2, 100], ['sell', 12, 250], ['sell', 3, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3]}], ['control 6', [['sell', 6, 250], ['sell', 3, 250], ['sell', 12, 200], ['sell', 1, 250], ['sell', 3, 250], ['purchase_return', 5, 150], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4, 5, 6]}]]]
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:
New purchases jump the FIFO queue when their cost matches the oldest layer.

x = [['buy', qty, unit_cost] | ['sell', qty, unit_price] | ['purchase_return', qty, unit_cost]]. Layers are kept oldest first; a buy at the same cost as the newest layer merges into it. A sale consumes layers oldest first (COGS) and records revenue; a sale exceeding on-hand quantity is rejected whole. A purchase return removes qty from the newest layer at that cost holding at least qty, else it is rejected. Emptied layers are removed. Return {'cogs', 'revenue', 'inventory': sum qty*cost, 'layers', 'rejected': event indexes}.

split: open-access


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

N = 1
observations = []
def solve(x):
    layers = []
    cogs = revenue = 0
    short = []
    for i, ev in enumerate(x):
        if ev[0] == 'buy':
            if layers and layers[-1][1] == ev[2]:
                layers[-1][0] += ev[1]
            else:
                layers.append([ev[1], ev[2]])
        elif ev[0] == 'sell':
            qty = ev[1]
            if (qty > layers[0][0]) if layers else True:
                short.append(i)
                continue
            revenue += qty * ev[2]
            while qty:
                head = layers[0]
                take = min(qty, head[0])
                cogs += take * head[1]
                head[0] -= take
                qty -= take
                if head[0] == 0:
                    layers.pop(0)
        elif ev[0] == 'purchase_return':
            match = [l for l in layers if l[1] == ev[2] and l[0] >= ev[1]]
            if not match:
                short.append(i)
                continue
            match[-1][0] -= ev[1]
            if match[-1][0] == 0:
                layers.remove(match[-1])
    inventory = sum(q * c for q, c in layers)
    return {'cogs': cogs, 'revenue': revenue, 'inventory': inventory, 'layers': layers, 'rejected': short}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: oversell check', [['buy', 5, 120], ['sell', 6, 200], ['sell', 3, 200], ['buy', 1, 100], ['buy', 5, 120], ['buy', 5, 100], ['sell', 6, 200], ['sell', 12, 250]], {'cogs': 1060, 'revenue': 1800, 'inventory': 740, 'layers': [[2, 120], [5, 100]], 'rejected': [1, 7]}], ['regression: oversell check, partial-repair probe', [['buy', 5, 150], ['sell', 3, 250], ['sell', 2, 250], ['buy', 10, 100], ['buy', 10, 120], ['purchase_return', 2, 100], ['purchase_return', 5, 100], ['buy', 10, 150], ['buy', 2, 120], ['purchase_return', 5, 100]], {'cogs': 750, 'revenue': 1250, 'inventory': 3240, 'layers': [[3, 100], [10, 120], [10, 150], [2, 120]], 'rejected': [9]}], ['control 1', [['sell', 3, 250], ['buy', 2, 120], ['purchase_return', 1, 100], ['buy', 5, 100], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 980, 'layers': [[2, 120], [5, 100], [2, 120]], 'rejected': [0, 2]}], ['control 2', [['buy', 1, 120], ['sell', 12, 200], ['sell', 2, 250], ['sell', 2, 250]], {'cogs': 0, 'revenue': 0, 'inventory': 120, 'layers': [[1, 120]], 'rejected': [1, 2, 3]}], ['control 3', [['buy', 5, 100], ['sell', 3, 250], ['sell', 12, 200]], {'cogs': 300, 'revenue': 750, 'inventory': 200, 'layers': [[2, 100]], 'rejected': [2]}], ['control 4', [['buy', 10, 120], ['purchase_return', 1, 100], ['sell', 1, 200], ['purchase_return', 2, 100], ['sell', 2, 200], ['purchase_return', 1, 120], ['buy', 10, 120], ['buy', 5, 120]], {'cogs': 360, 'revenue': 600, 'inventory': 2520, 'layers': [[21, 120]], 'rejected': [1, 3]}], ['control 5', [['sell', 12, 250], ['sell', 12, 200], ['buy', 5, 100], ['sell', 12, 250], ['sell', 12, 200], ['purchase_return', 1, 100], ['sell', 3, 250]], {'cogs': 300, 'revenue': 750, 'inventory': 100, 'layers': [[1, 100]], 'rejected': [0, 1, 3, 4]}]], [['regression: oversell check', [['purchase_return', 2, 100], ['sell', 3, 250], ['buy', 1, 150], ['buy', 1, 100], ['buy', 5, 100], ['buy', 1, 150], ['sell', 2, 200], ['sell', 1, 250], ['sell', 6, 250], ['sell', 6, 250]], {'cogs': 350, 'revenue': 650, 'inventory': 550, 'layers': [[4, 100], [1, 150]], 'rejected': [0, 1, 8, 9]}], ['regression: oversell check, partial-repair probe', [['buy', 1, 100], ['purchase_return', 5, 100], ['sell', 1, 250]], {'cogs': 100, 'revenue': 250, 'inventory': 0, 'layers': [], 'rejected': [1]}], ['control 1', [['sell', 12, 200], ['sell', 6, 250], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2]}], ['control 2', [['buy', 10, 100], ['sell', 12, 250], ['sell', 2, 250], ['sell', 12, 200], ['sell', 6, 200], ['buy', 1, 150], ['buy', 2, 120]], {'cogs': 800, 'revenue': 1700, 'inventory': 590, 'layers': [[2, 100], [1, 150], [2, 120]], 'rejected': [1, 3]}], ['control 3', [['purchase_return', 2, 100], ['sell', 12, 250], ['buy', 10, 100], ['buy', 1, 100], ['sell', 6, 200]], {'cogs': 600, 'revenue': 1200, 'inventory': 500, 'layers': [[5, 100]], 'rejected': [0, 1]}], ['control 4', [['buy', 10, 150], ['sell', 3, 250], ['sell', 12, 200], ['buy', 5, 120], ['sell', 3, 200], ['buy', 1, 100], ['sell', 1, 250], ['buy', 2, 100], ['sell', 12, 200], ['buy', 10, 100]], {'cogs': 1050, 'revenue': 1600, 'inventory': 2350, 'layers': [[3, 150], [5, 120], [13, 100]], 'rejected': [2, 8]}], ['control 5', [['sell', 2, 250], ['purchase_return', 1, 150], ['buy', 10, 100], ['buy', 10, 150], ['buy', 2, 150], ['buy', 2, 100], ['sell', 2, 250], ['sell', 3, 250], ['buy', 5, 120]], {'cogs': 500, 'revenue': 1250, 'inventory': 3100, 'layers': [[5, 100], [12, 150], [2, 100], [5, 120]], 'rejected': [0, 1]}]], [['regression: oversell check', [['buy', 1, 100], ['purchase_return', 5, 100], ['sell', 3, 200], ['buy', 1, 150], ['buy', 1, 150], ['sell', 3, 200], ['buy', 2, 120], ['buy', 10, 120]], {'cogs': 400, 'revenue': 600, 'inventory': 1440, 'layers': [[12, 120]], 'rejected': [1, 2]}], ['control 1', [['purchase_return', 5, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 320, 'layers': [[2, 100], [1, 120]], 'rejected': [0, 1]}], ['control 2', [['sell', 1, 250], ['buy', 5, 100], ['buy', 10, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 10, 100], ['sell', 6, 200], ['buy', 1, 120], ['buy', 10, 150], ['buy', 10, 150]], {'cogs': 800, 'revenue': 1700, 'inventory': 5020, 'layers': [[19, 100], [1, 120], [20, 150]], 'rejected': [0]}], ['control 3', [['purchase_return', 1, 100], ['sell', 1, 200], ['sell', 1, 250], ['sell', 3, 200], ['sell', 6, 200], ['buy', 10, 120], ['buy', 2, 150], ['buy', 2, 100], ['purchase_return', 2, 150]], {'cogs': 0, 'revenue': 0, 'inventory': 1400, 'layers': [[10, 120], [2, 100]], 'rejected': [0, 1, 2, 3, 4]}], ['control 4', [['purchase_return', 1, 100], ['buy', 2, 150], ['sell', 6, 200], ['sell', 2, 250], ['buy', 5, 120], ['buy', 5, 150], ['sell', 1, 250], ['purchase_return', 2, 100]], {'cogs': 420, 'revenue': 750, 'inventory': 1230, 'layers': [[4, 120], [5, 150]], 'rejected': [0, 2, 7]}], ['control 5', [['sell', 6, 200], ['sell', 12, 200], ['sell', 2, 200], ['sell', 2, 200], ['buy', 2, 100], ['purchase_return', 1, 120], ['buy', 2, 150], ['sell', 2, 200], ['sell', 2, 200], ['sell', 2, 200]], {'cogs': 500, 'revenue': 800, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 5, 9]}], ['control 6', [['sell', 2, 250], ['buy', 5, 100], ['purchase_return', 5, 150], ['sell', 1, 200], ['buy', 2, 150], ['sell', 2, 250], ['buy', 2, 100], ['buy', 5, 150], ['buy', 5, 150]], {'cogs': 300, 'revenue': 700, 'inventory': 2200, 'layers': [[2, 100], [2, 150], [2, 100], [10, 150]], 'rejected': [0, 2]}]], [['regression: oversell check', [['sell', 1, 250], ['sell', 3, 200], ['purchase_return', 1, 100], ['buy', 2, 120], ['buy', 5, 150], ['sell', 3, 200], ['sell', 1, 200], ['sell', 6, 250], ['buy', 2, 120]], {'cogs': 540, 'revenue': 800, 'inventory': 690, 'layers': [[3, 150], [2, 120]], 'rejected': [0, 1, 2, 7]}], ['regression: oversell check, partial-repair probe', [['purchase_return', 2, 100], ['buy', 10, 100], ['sell', 12, 250], ['sell', 1, 200], ['purchase_return', 1, 150], ['sell', 6, 200], ['buy', 5, 100], ['purchase_return', 2, 100], ['sell', 6, 250], ['sell', 6, 200]], {'cogs': 1300, 'revenue': 2900, 'inventory': 0, 'layers': [], 'rejected': [0, 2, 4, 9]}], ['control 1', [['buy', 1, 100], ['purchase_return', 2, 150], ['purchase_return', 1, 120], ['purchase_return', 2, 100], ['buy', 5, 100], ['buy', 10, 100], ['buy', 1, 150], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1870, 'layers': [[16, 100], [1, 150], [1, 120]], 'rejected': [1, 2, 3]}], ['control 2', [['sell', 12, 200], ['sell', 12, 250], ['buy', 2, 150], ['sell', 12, 250], ['buy', 2, 150], ['buy', 1, 100], ['buy', 5, 120], ['buy', 10, 150], ['sell', 3, 200], ['buy', 2, 150]], {'cogs': 450, 'revenue': 600, 'inventory': 2650, 'layers': [[1, 150], [1, 100], [5, 120], [12, 150]], 'rejected': [0, 1, 3]}], ['control 3', [['sell', 3, 250], ['purchase_return', 1, 150], ['purchase_return', 2, 120], ['sell', 6, 200], ['purchase_return', 2, 100]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4]}], ['control 4', [['purchase_return', 2, 120], ['sell', 6, 200], ['sell', 2, 250], ['purchase_return', 2, 100], ['buy', 5, 100], ['buy', 2, 120], ['buy', 5, 120], ['sell', 1, 200]], {'cogs': 100, 'revenue': 200, 'inventory': 1240, 'layers': [[4, 100], [7, 120]], 'rejected': [0, 1, 2, 3]}], ['control 5', [['sell', 6, 250], ['sell', 2, 250], ['sell', 3, 250], ['sell', 12, 250], ['sell', 12, 250], ['sell', 3, 250], ['buy', 1, 100], ['buy', 5, 120], ['buy', 5, 150], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1690, 'layers': [[1, 100], [5, 120], [5, 150], [2, 120]], 'rejected': [0, 1, 2, 3, 4, 5]}]], [['regression: oversell check', [['buy', 10, 100], ['buy', 10, 150], ['purchase_return', 5, 100], ['sell', 6, 200], ['sell', 3, 200], ['sell', 2, 200]], {'cogs': 1400, 'revenue': 2200, 'inventory': 600, 'layers': [[4, 150]], 'rejected': []}], ['regression: oversell check, partial-repair probe', [['buy', 5, 100], ['sell', 2, 200], ['sell', 3, 250], ['buy', 5, 120], ['buy', 10, 150], ['buy', 10, 100], ['sell', 2, 200], ['purchase_return', 2, 100], ['purchase_return', 1, 100]], {'cogs': 740, 'revenue': 1550, 'inventory': 2560, 'layers': [[3, 120], [10, 150], [7, 100]], 'rejected': []}], ['control 1', [['purchase_return', 2, 100], ['sell', 1, 200], ['buy', 5, 100], ['buy', 5, 100], ['purchase_return', 1, 150], ['sell', 2, 250], ['buy', 1, 100], ['sell', 1, 200]], {'cogs': 300, 'revenue': 700, 'inventory': 800, 'layers': [[8, 100]], 'rejected': [0, 1, 4]}], ['control 2', [['purchase_return', 1, 100], ['buy', 1, 100], ['sell', 3, 200], ['buy', 10, 100], ['buy', 5, 100], ['sell', 2, 200], ['purchase_return', 2, 150]], {'cogs': 200, 'revenue': 400, 'inventory': 1400, 'layers': [[14, 100]], 'rejected': [0, 2, 6]}], ['control 3', [['buy', 10, 120], ['buy', 1, 120], ['purchase_return', 2, 150], ['sell', 2, 250], ['buy', 1, 100]], {'cogs': 240, 'revenue': 500, 'inventory': 1180, 'layers': [[9, 120], [1, 100]], 'rejected': [2]}], ['control 4', [['sell', 6, 250], ['purchase_return', 2, 100], ['sell', 12, 250], ['sell', 3, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3]}], ['control 5', [['sell', 6, 250], ['sell', 3, 250], ['sell', 12, 200], ['sell', 1, 250], ['sell', 3, 250], ['purchase_return', 5, 150], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4, 5, 6]}]]]
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):
    layers = []
    cogs = revenue = 0
    short = []
    for i, ev in enumerate(x):
        if ev[0] == 'buy':
            if layers and layers[-1][1] == ev[2]:
                layers[-1][0] += ev[1]
            else:
                layers.append([ev[1], ev[2]])
        elif ev[0] == 'sell':
            qty = ev[1]
            if qty >= sum(l[0] for l in layers):
                short.append(i)
                continue
            revenue += qty * ev[2]
            while qty:
                head = layers[0]
                take = min(qty, head[0])
                cogs += take * head[1]
                head[0] -= take
                qty -= take
                if head[0] == 0:
                    layers.pop(0)
        elif ev[0] == 'purchase_return':
            match = [l for l in layers if l[1] == ev[2] and l[0] >= ev[1]]
            if not match:
                short.append(i)
                continue
            match[-1][0] -= ev[1]
            if match[-1][0] == 0:
                layers.remove(match[-1])
    inventory = sum(q * c for q, c in layers)
    return {'cogs': cogs, 'revenue': revenue, 'inventory': inventory, 'layers': layers, 'rejected': short}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: oversell check', [['buy', 5, 120], ['sell', 6, 200], ['sell', 3, 200], ['buy', 1, 100], ['buy', 5, 120], ['buy', 5, 100], ['sell', 6, 200], ['sell', 12, 250]], {'cogs': 1060, 'revenue': 1800, 'inventory': 740, 'layers': [[2, 120], [5, 100]], 'rejected': [1, 7]}], ['regression: oversell check, partial-repair probe', [['buy', 5, 150], ['sell', 3, 250], ['sell', 2, 250], ['buy', 10, 100], ['buy', 10, 120], ['purchase_return', 2, 100], ['purchase_return', 5, 100], ['buy', 10, 150], ['buy', 2, 120], ['purchase_return', 5, 100]], {'cogs': 750, 'revenue': 1250, 'inventory': 3240, 'layers': [[3, 100], [10, 120], [10, 150], [2, 120]], 'rejected': [9]}], ['control 1', [['sell', 3, 250], ['buy', 2, 120], ['purchase_return', 1, 100], ['buy', 5, 100], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 980, 'layers': [[2, 120], [5, 100], [2, 120]], 'rejected': [0, 2]}], ['control 2', [['buy', 1, 120], ['sell', 12, 200], ['sell', 2, 250], ['sell', 2, 250]], {'cogs': 0, 'revenue': 0, 'inventory': 120, 'layers': [[1, 120]], 'rejected': [1, 2, 3]}], ['control 3', [['buy', 5, 100], ['sell', 3, 250], ['sell', 12, 200]], {'cogs': 300, 'revenue': 750, 'inventory': 200, 'layers': [[2, 100]], 'rejected': [2]}], ['control 4', [['buy', 10, 120], ['purchase_return', 1, 100], ['sell', 1, 200], ['purchase_return', 2, 100], ['sell', 2, 200], ['purchase_return', 1, 120], ['buy', 10, 120], ['buy', 5, 120]], {'cogs': 360, 'revenue': 600, 'inventory': 2520, 'layers': [[21, 120]], 'rejected': [1, 3]}], ['control 5', [['sell', 12, 250], ['sell', 12, 200], ['buy', 5, 100], ['sell', 12, 250], ['sell', 12, 200], ['purchase_return', 1, 100], ['sell', 3, 250]], {'cogs': 300, 'revenue': 750, 'inventory': 100, 'layers': [[1, 100]], 'rejected': [0, 1, 3, 4]}]], [['regression: oversell check', [['purchase_return', 2, 100], ['sell', 3, 250], ['buy', 1, 150], ['buy', 1, 100], ['buy', 5, 100], ['buy', 1, 150], ['sell', 2, 200], ['sell', 1, 250], ['sell', 6, 250], ['sell', 6, 250]], {'cogs': 350, 'revenue': 650, 'inventory': 550, 'layers': [[4, 100], [1, 150]], 'rejected': [0, 1, 8, 9]}], ['regression: oversell check, partial-repair probe', [['buy', 1, 100], ['purchase_return', 5, 100], ['sell', 1, 250]], {'cogs': 100, 'revenue': 250, 'inventory': 0, 'layers': [], 'rejected': [1]}], ['control 1', [['sell', 12, 200], ['sell', 6, 250], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2]}], ['control 2', [['buy', 10, 100], ['sell', 12, 250], ['sell', 2, 250], ['sell', 12, 200], ['sell', 6, 200], ['buy', 1, 150], ['buy', 2, 120]], {'cogs': 800, 'revenue': 1700, 'inventory': 590, 'layers': [[2, 100], [1, 150], [2, 120]], 'rejected': [1, 3]}], ['control 3', [['purchase_return', 2, 100], ['sell', 12, 250], ['buy', 10, 100], ['buy', 1, 100], ['sell', 6, 200]], {'cogs': 600, 'revenue': 1200, 'inventory': 500, 'layers': [[5, 100]], 'rejected': [0, 1]}], ['control 4', [['buy', 10, 150], ['sell', 3, 250], ['sell', 12, 200], ['buy', 5, 120], ['sell', 3, 200], ['buy', 1, 100], ['sell', 1, 250], ['buy', 2, 100], ['sell', 12, 200], ['buy', 10, 100]], {'cogs': 1050, 'revenue': 1600, 'inventory': 2350, 'layers': [[3, 150], [5, 120], [13, 100]], 'rejected': [2, 8]}], ['control 5', [['sell', 2, 250], ['purchase_return', 1, 150], ['buy', 10, 100], ['buy', 10, 150], ['buy', 2, 150], ['buy', 2, 100], ['sell', 2, 250], ['sell', 3, 250], ['buy', 5, 120]], {'cogs': 500, 'revenue': 1250, 'inventory': 3100, 'layers': [[5, 100], [12, 150], [2, 100], [5, 120]], 'rejected': [0, 1]}]], [['regression: oversell check', [['buy', 1, 100], ['purchase_return', 5, 100], ['sell', 3, 200], ['buy', 1, 150], ['buy', 1, 150], ['sell', 3, 200], ['buy', 2, 120], ['buy', 10, 120]], {'cogs': 400, 'revenue': 600, 'inventory': 1440, 'layers': [[12, 120]], 'rejected': [1, 2]}], ['control 1', [['purchase_return', 5, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 320, 'layers': [[2, 100], [1, 120]], 'rejected': [0, 1]}], ['control 2', [['sell', 1, 250], ['buy', 5, 100], ['buy', 10, 100], ['sell', 2, 250], ['buy', 2, 100], ['buy', 10, 100], ['sell', 6, 200], ['buy', 1, 120], ['buy', 10, 150], ['buy', 10, 150]], {'cogs': 800, 'revenue': 1700, 'inventory': 5020, 'layers': [[19, 100], [1, 120], [20, 150]], 'rejected': [0]}], ['control 3', [['purchase_return', 1, 100], ['sell', 1, 200], ['sell', 1, 250], ['sell', 3, 200], ['sell', 6, 200], ['buy', 10, 120], ['buy', 2, 150], ['buy', 2, 100], ['purchase_return', 2, 150]], {'cogs': 0, 'revenue': 0, 'inventory': 1400, 'layers': [[10, 120], [2, 100]], 'rejected': [0, 1, 2, 3, 4]}], ['control 4', [['purchase_return', 1, 100], ['buy', 2, 150], ['sell', 6, 200], ['sell', 2, 250], ['buy', 5, 120], ['buy', 5, 150], ['sell', 1, 250], ['purchase_return', 2, 100]], {'cogs': 420, 'revenue': 750, 'inventory': 1230, 'layers': [[4, 120], [5, 150]], 'rejected': [0, 2, 7]}], ['control 5', [['sell', 6, 200], ['sell', 12, 200], ['sell', 2, 200], ['sell', 2, 200], ['buy', 2, 100], ['purchase_return', 1, 120], ['buy', 2, 150], ['sell', 2, 200], ['sell', 2, 200], ['sell', 2, 200]], {'cogs': 500, 'revenue': 800, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 5, 9]}], ['control 6', [['sell', 2, 250], ['buy', 5, 100], ['purchase_return', 5, 150], ['sell', 1, 200], ['buy', 2, 150], ['sell', 2, 250], ['buy', 2, 100], ['buy', 5, 150], ['buy', 5, 150]], {'cogs': 300, 'revenue': 700, 'inventory': 2200, 'layers': [[2, 100], [2, 150], [2, 100], [10, 150]], 'rejected': [0, 2]}]], [['regression: oversell check', [['sell', 1, 250], ['sell', 3, 200], ['purchase_return', 1, 100], ['buy', 2, 120], ['buy', 5, 150], ['sell', 3, 200], ['sell', 1, 200], ['sell', 6, 250], ['buy', 2, 120]], {'cogs': 540, 'revenue': 800, 'inventory': 690, 'layers': [[3, 150], [2, 120]], 'rejected': [0, 1, 2, 7]}], ['regression: oversell check, partial-repair probe', [['purchase_return', 2, 100], ['buy', 10, 100], ['sell', 12, 250], ['sell', 1, 200], ['purchase_return', 1, 150], ['sell', 6, 200], ['buy', 5, 100], ['purchase_return', 2, 100], ['sell', 6, 250], ['sell', 6, 200]], {'cogs': 1300, 'revenue': 2900, 'inventory': 0, 'layers': [], 'rejected': [0, 2, 4, 9]}], ['control 1', [['buy', 1, 100], ['purchase_return', 2, 150], ['purchase_return', 1, 120], ['purchase_return', 2, 100], ['buy', 5, 100], ['buy', 10, 100], ['buy', 1, 150], ['buy', 1, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1870, 'layers': [[16, 100], [1, 150], [1, 120]], 'rejected': [1, 2, 3]}], ['control 2', [['sell', 12, 200], ['sell', 12, 250], ['buy', 2, 150], ['sell', 12, 250], ['buy', 2, 150], ['buy', 1, 100], ['buy', 5, 120], ['buy', 10, 150], ['sell', 3, 200], ['buy', 2, 150]], {'cogs': 450, 'revenue': 600, 'inventory': 2650, 'layers': [[1, 150], [1, 100], [5, 120], [12, 150]], 'rejected': [0, 1, 3]}], ['control 3', [['sell', 3, 250], ['purchase_return', 1, 150], ['purchase_return', 2, 120], ['sell', 6, 200], ['purchase_return', 2, 100]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4]}], ['control 4', [['purchase_return', 2, 120], ['sell', 6, 200], ['sell', 2, 250], ['purchase_return', 2, 100], ['buy', 5, 100], ['buy', 2, 120], ['buy', 5, 120], ['sell', 1, 200]], {'cogs': 100, 'revenue': 200, 'inventory': 1240, 'layers': [[4, 100], [7, 120]], 'rejected': [0, 1, 2, 3]}], ['control 5', [['sell', 6, 250], ['sell', 2, 250], ['sell', 3, 250], ['sell', 12, 250], ['sell', 12, 250], ['sell', 3, 250], ['buy', 1, 100], ['buy', 5, 120], ['buy', 5, 150], ['buy', 2, 120]], {'cogs': 0, 'revenue': 0, 'inventory': 1690, 'layers': [[1, 100], [5, 120], [5, 150], [2, 120]], 'rejected': [0, 1, 2, 3, 4, 5]}]], [['regression: oversell check', [['buy', 10, 100], ['buy', 10, 150], ['purchase_return', 5, 100], ['sell', 6, 200], ['sell', 3, 200], ['sell', 2, 200]], {'cogs': 1400, 'revenue': 2200, 'inventory': 600, 'layers': [[4, 150]], 'rejected': []}], ['regression: oversell check, partial-repair probe', [['buy', 5, 100], ['sell', 2, 200], ['sell', 3, 250], ['buy', 5, 120], ['buy', 10, 150], ['buy', 10, 100], ['sell', 2, 200], ['purchase_return', 2, 100], ['purchase_return', 1, 100]], {'cogs': 740, 'revenue': 1550, 'inventory': 2560, 'layers': [[3, 120], [10, 150], [7, 100]], 'rejected': []}], ['control 1', [['purchase_return', 2, 100], ['sell', 1, 200], ['buy', 5, 100], ['buy', 5, 100], ['purchase_return', 1, 150], ['sell', 2, 250], ['buy', 1, 100], ['sell', 1, 200]], {'cogs': 300, 'revenue': 700, 'inventory': 800, 'layers': [[8, 100]], 'rejected': [0, 1, 4]}], ['control 2', [['purchase_return', 1, 100], ['buy', 1, 100], ['sell', 3, 200], ['buy', 10, 100], ['buy', 5, 100], ['sell', 2, 200], ['purchase_return', 2, 150]], {'cogs': 200, 'revenue': 400, 'inventory': 1400, 'layers': [[14, 100]], 'rejected': [0, 2, 6]}], ['control 3', [['buy', 10, 120], ['buy', 1, 120], ['purchase_return', 2, 150], ['sell', 2, 250], ['buy', 1, 100]], {'cogs': 240, 'revenue': 500, 'inventory': 1180, 'layers': [[9, 120], [1, 100]], 'rejected': [2]}], ['control 4', [['sell', 6, 250], ['purchase_return', 2, 100], ['sell', 12, 250], ['sell', 3, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3]}], ['control 5', [['sell', 6, 250], ['sell', 3, 250], ['sell', 12, 200], ['sell', 1, 250], ['sell', 3, 250], ['purchase_return', 5, 150], ['sell', 6, 200]], {'cogs': 0, 'revenue': 0, 'inventory': 0, 'layers': [], 'rejected': [0, 1, 2, 3, 4, 5, 6]}]]]
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:
Sales that span two cost layers are rejected as stock-outs.

x = [['buy', qty, unit_cost] | ['sell', qty, unit_price] | ['purchase_return', qty, unit_cost]]. Layers are kept oldest first; a buy at the same cost as the newest layer merges into it. A sale consumes layers oldest first (COGS) and records revenue; a sale exceeding on-hand quantity is rejected whole. A purchase return removes qty from the newest layer at that cost holding at least qty, else it is rejected. Emptied layers are removed. Return {'cogs', 'revenue', 'inventory': sum qty*cost, 'layers', 'rejected': event indexes}.

split: open-access