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

N = 1
observations = []
def solve(x):
    cur = x['current']
    locked = set(x['locked'])
    todo = []
    for p, pos in x['need']:
        if cur.get(p) == pos:
            continue
        if p in locked:
            return {'result': 'blocked:' + p, 'starts': {}, 'done_s': 0}
        todo.append(p)
    slots = [0] * x['max_parallel']
    starts = {}
    for p in todo:
        k = min(range(len(slots)), key=lambda i: (slots[i], i))
        starts[p] = slots[k]
        slots[k] += x['throw_s'][p] if p in x['throw_s'] else x['default_throw_s']
    done = sum(slots) if todo else 0
    return {'result': 'set', 'starts': starts, 'done_s': done}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('sampled regression 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('regression: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('control 4', {'need': [['P1', 'N'], ['P5', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P3': 4, 'P5': 3, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 7', {'need': [['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 10', {'need': [['P3', 'R'], ['P4', 'N']], 'current': {'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P1', 'P5'], 'max_parallel': 3, 'throw_s': {'P2': 3, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0}, 'done_s': 4})], [('regression: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 30', {'need': [['P6', 'N'], ['P5', 'R'], ['P3', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 3, 'P4': 6, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0, 'P1': 0}, 'done_s': 6}), ('sampled regression 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('control 12', {'need': [['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P6'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 18', {'need': [['P2', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P3': 0}, 'done_s': 6})], [('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('regression: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('sampled regression 76', {'need': [['P3', 'R'], ['P5', 'N'], ['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': ['P2'], 'max_parallel': 3, 'throw_s': {'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P5': 0, 'P6': 0}, 'done_s': 5}), ('control 8', {'need': [['P3', 'R'], ['P1', 'N'], ['P6', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('control 23', {'need': [['P3', 'N'], ['P4', 'N'], ['P1', 'R'], ['P6', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P4': 3, 'P5': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 3}, 'done_s': 6}), ('control 26', {'need': [['P1', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P5', 'P6'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 29', {'need': [['P4', 'N'], ['P2', 'N'], ['P1', 'N'], ['P5', 'N'], ['P6', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 6, 'P4': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P1': 6}, 'done_s': 10})], [('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('sampled regression 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('sampled regression 13', {'need': [['P5', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 3, 'P2': 3, 'P3': 6, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P5': 0, 'P2': 0}, 'done_s': 5}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 34', {'need': [['P3', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 37', {'need': [['P5', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 40', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('sampled regression 30', {'need': [['P6', 'N'], ['P5', 'R'], ['P3', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 3, 'P4': 6, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0, 'P1': 0}, 'done_s': 6}), ('control 20', {'need': [['P6', 'N'], ['P5', 'N'], ['P2', 'N'], ['P4', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'N'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 6, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0}, 'done_s': 6}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('control 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 48', {'need': [['P3', 'R']], 'current': {'P1': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P4'], 'max_parallel': 1, 'throw_s': {'P4': 6, 'P5': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 51', {'need': [['P6', 'R'], ['P5', 'N'], ['P1', 'R'], ['P4', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

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

N = 1
observations = []
def solve(x):
    cur = x['current']
    locked = set(x['locked'])
    todo = []
    for p, pos in x['need']:
        if cur.get(p) == pos:
            continue
        if p in locked:
            return {'result': 'blocked:' + p, 'starts': {}, 'done_s': 0}
        todo.append(p)
    slots = [0] * x['max_parallel']
    starts = {}
    for p in todo:
        k = min(range(len(slots)), key=lambda i: (slots[i], i))
        starts[p] = slots[k]
        slots[k] += x['throw_s'][p] if p in x['throw_s'] else x['default_throw_s']
    done = max(starts.values()) if todo else 0
    return {'result': 'set', 'starts': starts, 'done_s': done}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('sampled regression 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('regression: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('control 4', {'need': [['P1', 'N'], ['P5', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P3': 4, 'P5': 3, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 7', {'need': [['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 10', {'need': [['P3', 'R'], ['P4', 'N']], 'current': {'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P1', 'P5'], 'max_parallel': 3, 'throw_s': {'P2': 3, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0}, 'done_s': 4})], [('regression: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 30', {'need': [['P6', 'N'], ['P5', 'R'], ['P3', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 3, 'P4': 6, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0, 'P1': 0}, 'done_s': 6}), ('sampled regression 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('control 12', {'need': [['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P6'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 18', {'need': [['P2', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P3': 0}, 'done_s': 6})], [('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('regression: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('sampled regression 76', {'need': [['P3', 'R'], ['P5', 'N'], ['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': ['P2'], 'max_parallel': 3, 'throw_s': {'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P5': 0, 'P6': 0}, 'done_s': 5}), ('control 8', {'need': [['P3', 'R'], ['P1', 'N'], ['P6', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('control 23', {'need': [['P3', 'N'], ['P4', 'N'], ['P1', 'R'], ['P6', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P4': 3, 'P5': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 3}, 'done_s': 6}), ('control 26', {'need': [['P1', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P5', 'P6'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 29', {'need': [['P4', 'N'], ['P2', 'N'], ['P1', 'N'], ['P5', 'N'], ['P6', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 6, 'P4': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P1': 6}, 'done_s': 10})], [('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('sampled regression 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('sampled regression 13', {'need': [['P5', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 3, 'P2': 3, 'P3': 6, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P5': 0, 'P2': 0}, 'done_s': 5}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 34', {'need': [['P3', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 37', {'need': [['P5', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 40', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('sampled regression 30', {'need': [['P6', 'N'], ['P5', 'R'], ['P3', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 3, 'P4': 6, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0, 'P1': 0}, 'done_s': 6}), ('control 20', {'need': [['P6', 'N'], ['P5', 'N'], ['P2', 'N'], ['P4', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'N'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 6, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0}, 'done_s': 6}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('control 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 48', {'need': [['P3', 'R']], 'current': {'P1': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P4'], 'max_parallel': 1, 'throw_s': {'P4': 6, 'P5': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 51', {'need': [['P6', 'R'], ['P5', 'N'], ['P1', 'R'], ['P4', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
The route is reported ready at the wrong time.

A route needs points in given lies (processed in list order). Points already detected in the needed lie are skipped; an undetected point (missing from current) must be thrown. A point that must move but is locked by another route blocks the whole request (blocked:<p>, nothing thrown). At most max_parallel points move at once: each point starts on the earliest-free supply slot (lowest index on ties) and takes its own throw time or the default. Return the start time per thrown point and the time all have finished.

split: open-access


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

N = 1
observations = []
def solve(x):
    cur = x['current']
    locked = set(x['locked'])
    todo = []
    for p, pos in x['need']:
        if p not in cur or cur[p] == pos:
            continue
        if p in locked:
            return {'result': 'blocked:' + p, 'starts': {}, 'done_s': 0}
        todo.append(p)
    slots = [0] * x['max_parallel']
    starts = {}
    for p in todo:
        k = min(range(len(slots)), key=lambda i: (slots[i], i))
        starts[p] = slots[k]
        slots[k] += x['throw_s'][p] if p in x['throw_s'] else x['default_throw_s']
    done = max(slots) if todo else 0
    return {'result': 'set', 'starts': starts, 'done_s': done}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 17', {'need': [['P2', 'N'], ['P5', 'N'], ['P4', 'N']], 'current': {'P1': 'R', 'P3': 'R', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 3, 'P3': 3, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P5': 5}, 'done_s': 11}), ('sampled regression 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('control 4', {'need': [['P1', 'N'], ['P5', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P3': 4, 'P5': 3, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 7', {'need': [['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 57', {'need': [['P6', 'R'], ['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'N', 'P5': 'N'}, 'locked': ['P2', 'P6'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P3': 3, 'P4': 3, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P6', 'starts': {}, 'done_s': 0}), ('sampled regression 31', {'need': [['P4', 'N'], ['P6', 'R'], ['P3', 'R'], ['P5', 'R'], ['P2', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 4, 'P4': 4, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 0, 'P3': 0, 'P5': 4}, 'done_s': 9}), ('boundary: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('boundary: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('control 12', {'need': [['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P6'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('sampled regression 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 18', {'need': [['P2', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P3': 0}, 'done_s': 6})], [('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 16', {'need': [['P4', 'R'], ['P2', 'N']], 'current': {'P1': 'N', 'P3': 'R', 'P4': 'N', 'P5': 'R', 'P6': 'R'}, 'locked': ['P6'], 'max_parallel': 3, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P2': 0}, 'done_s': 3}), ('sampled regression 62', {'need': [['P6', 'N'], ['P5', 'N'], ['P1', 'N'], ['P2', 'N'], ['P4', 'N']], 'current': {'P3': 'R', 'P4': 'N', 'P5': 'N', 'P6': 'N'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 6, 'P4': 3, 'P5': 3, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 6}), ('boundary: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('sampled regression 23', {'need': [['P3', 'N'], ['P4', 'N'], ['P1', 'R'], ['P6', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P4': 3, 'P5': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 3}, 'done_s': 6}), ('control 26', {'need': [['P1', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P5', 'P6'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('sampled regression 29', {'need': [['P4', 'N'], ['P2', 'N'], ['P1', 'N'], ['P5', 'N'], ['P6', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 6, 'P4': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P1': 6}, 'done_s': 10})], [('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 55', {'need': [['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P1', 'N'], ['P5', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('sampled regression 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('boundary: points with individual throw times', {'need': [['P4', 'R'], ['P5', 'N']], 'current': {'P4': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P5': 3}, 'done_s': 8}), ('control 34', {'need': [['P3', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 37', {'need': [['P5', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 40', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 31', {'need': [['P4', 'N'], ['P6', 'R'], ['P3', 'R'], ['P5', 'R'], ['P2', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 4, 'P4': 4, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 0, 'P3': 0, 'P5': 4}, 'done_s': 9}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 48', {'need': [['P3', 'R']], 'current': {'P1': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P4'], 'max_parallel': 1, 'throw_s': {'P4': 6, 'P5': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 51', {'need': [['P6', 'R'], ['P5', 'N'], ['P1', 'R'], ['P4', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

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

N = 1
observations = []
def solve(x):
    cur = x['current']
    locked = set(x['locked'])
    todo = []
    for p, pos in x['need']:
        if cur.get(p, pos) == pos:
            continue
        if p in locked:
            return {'result': 'blocked:' + p, 'starts': {}, 'done_s': 0}
        todo.append(p)
    slots = [0] * x['max_parallel']
    starts = {}
    for p in todo:
        k = min(range(len(slots)), key=lambda i: (slots[i], i))
        starts[p] = slots[k]
        slots[k] += x['throw_s'][p] if p in x['throw_s'] else x['default_throw_s']
    done = max(slots) if todo else 0
    return {'result': 'set', 'starts': starts, 'done_s': done}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 17', {'need': [['P2', 'N'], ['P5', 'N'], ['P4', 'N']], 'current': {'P1': 'R', 'P3': 'R', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 3, 'P3': 3, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P5': 5}, 'done_s': 11}), ('sampled regression 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('control 4', {'need': [['P1', 'N'], ['P5', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P3': 4, 'P5': 3, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 7', {'need': [['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 57', {'need': [['P6', 'R'], ['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'N', 'P5': 'N'}, 'locked': ['P2', 'P6'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P3': 3, 'P4': 3, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P6', 'starts': {}, 'done_s': 0}), ('sampled regression 31', {'need': [['P4', 'N'], ['P6', 'R'], ['P3', 'R'], ['P5', 'R'], ['P2', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 4, 'P4': 4, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 0, 'P3': 0, 'P5': 4}, 'done_s': 9}), ('boundary: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('boundary: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('control 12', {'need': [['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P6'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('sampled regression 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 18', {'need': [['P2', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P3': 0}, 'done_s': 6})], [('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 16', {'need': [['P4', 'R'], ['P2', 'N']], 'current': {'P1': 'N', 'P3': 'R', 'P4': 'N', 'P5': 'R', 'P6': 'R'}, 'locked': ['P6'], 'max_parallel': 3, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P2': 0}, 'done_s': 3}), ('sampled regression 62', {'need': [['P6', 'N'], ['P5', 'N'], ['P1', 'N'], ['P2', 'N'], ['P4', 'N']], 'current': {'P3': 'R', 'P4': 'N', 'P5': 'N', 'P6': 'N'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 6, 'P4': 3, 'P5': 3, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 6}), ('boundary: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('sampled regression 23', {'need': [['P3', 'N'], ['P4', 'N'], ['P1', 'R'], ['P6', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P4': 3, 'P5': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 3}, 'done_s': 6}), ('control 26', {'need': [['P1', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P5', 'P6'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('sampled regression 29', {'need': [['P4', 'N'], ['P2', 'N'], ['P1', 'N'], ['P5', 'N'], ['P6', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 6, 'P4': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P1': 6}, 'done_s': 10})], [('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 55', {'need': [['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P1', 'N'], ['P5', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('sampled regression 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('boundary: points with individual throw times', {'need': [['P4', 'R'], ['P5', 'N']], 'current': {'P4': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P5': 3}, 'done_s': 8}), ('control 34', {'need': [['P3', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 37', {'need': [['P5', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 40', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('sampled regression 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('sampled regression 31', {'need': [['P4', 'N'], ['P6', 'R'], ['P3', 'R'], ['P5', 'R'], ['P2', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 4, 'P4': 4, 'P6': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 0, 'P3': 0, 'P5': 4}, 'done_s': 9}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 48', {'need': [['P3', 'R']], 'current': {'P1': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P4'], 'max_parallel': 1, 'throw_s': {'P4': 6, 'P5': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 51', {'need': [['P6', 'R'], ['P5', 'N'], ['P1', 'R'], ['P4', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
A point without detection is assumed to lie correctly and is not thrown.

A route needs points in given lies (processed in list order). Points already detected in the needed lie are skipped; an undetected point (missing from current) must be thrown. A point that must move but is locked by another route blocks the whole request (blocked:<p>, nothing thrown). At most max_parallel points move at once: each point starts on the earliest-free supply slot (lowest index on ties) and takes its own throw time or the default. Return the start time per thrown point and the time all have finished.

split: open-access


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

N = 1
observations = []
def solve(x):
    cur = x['current']
    locked = set(x['locked'])
    todo = []
    for p, pos in x['need']:
        if cur.get(p) == pos:
            continue
        if p in locked:
            return {'result': 'blocked:' + p, 'starts': {}, 'done_s': 0}
        todo.append(p)
    slots = [0] * x['max_parallel']
    starts = {}
    for p in todo:
        k = len(starts) % len(slots)
        starts[p] = slots[k]
        slots[k] += x['throw_s'][p] if p in x['throw_s'] else x['default_throw_s']
    done = max(slots) if todo else 0
    return {'result': 'set', 'starts': starts, 'done_s': done}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('control 49', {'need': [['P5', 'R'], ['P3', 'N'], ['P1', 'N'], ['P4', 'R'], ['P2', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P1': 0, 'P4': 3, 'P2': 5}, 'done_s': 10}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('control 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('control 4', {'need': [['P1', 'N'], ['P5', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P3': 4, 'P5': 3, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 7', {'need': [['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('boundary: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 12', {'need': [['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P6'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 18', {'need': [['P2', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P3': 0}, 'done_s': 6})], [('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('control 49', {'need': [['P5', 'R'], ['P3', 'N'], ['P1', 'N'], ['P4', 'R'], ['P2', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P1': 0, 'P4': 3, 'P2': 5}, 'done_s': 10}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('boundary: points with individual throw times', {'need': [['P4', 'R'], ['P5', 'N']], 'current': {'P4': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P5': 3}, 'done_s': 8}), ('control 23', {'need': [['P3', 'N'], ['P4', 'N'], ['P1', 'R'], ['P6', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P4': 3, 'P5': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 3}, 'done_s': 6}), ('control 26', {'need': [['P1', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P5', 'P6'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 29', {'need': [['P4', 'N'], ['P2', 'N'], ['P1', 'N'], ['P5', 'N'], ['P6', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 6, 'P4': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P1': 6}, 'done_s': 10})], [('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('boundary: points with individual throw times', {'need': [['P4', 'R'], ['P5', 'N']], 'current': {'P4': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P5': 3}, 'done_s': 8}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 34', {'need': [['P3', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 37', {'need': [['P5', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 40', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('control 49', {'need': [['P5', 'R'], ['P3', 'N'], ['P1', 'N'], ['P4', 'R'], ['P2', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P1': 0, 'P4': 3, 'P2': 5}, 'done_s': 10}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('control 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 48', {'need': [['P3', 'R']], 'current': {'P1': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P4'], 'max_parallel': 1, 'throw_s': {'P4': 6, 'P5': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 51', {'need': [['P6', 'R'], ['P5', 'N'], ['P1', 'R'], ['P4', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

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

N = 1
observations = []
def solve(x):
    cur = x['current']
    locked = set(x['locked'])
    todo = []
    for p, pos in x['need']:
        if cur.get(p) == pos:
            continue
        if p in locked:
            return {'result': 'blocked:' + p, 'starts': {}, 'done_s': 0}
        todo.append(p)
    slots = [0] * x['max_parallel']
    starts = {}
    for p in todo:
        k = min(range(len(slots)), key=lambda i: (slots[i] > 0, i))
        starts[p] = slots[k]
        slots[k] += x['throw_s'][p] if p in x['throw_s'] else x['default_throw_s']
    done = max(slots) if todo else 0
    return {'result': 'set', 'starts': starts, 'done_s': done}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('control 49', {'need': [['P5', 'R'], ['P3', 'N'], ['P1', 'N'], ['P4', 'R'], ['P2', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P1': 0, 'P4': 3, 'P2': 5}, 'done_s': 10}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('control 1', {'need': [['P3', 'R'], ['P6', 'N'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P6': 0, 'P1': 5}, 'done_s': 11}), ('control 4', {'need': [['P1', 'N'], ['P5', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P3': 4, 'P5': 3, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 7', {'need': [['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('boundary: three points on two supplies', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3}, 'done_s': 8}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 12', {'need': [['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P6'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 15', {'need': [['P1', 'N'], ['P5', 'R'], ['P4', 'R'], ['P3', 'R'], ['P2', 'R']], 'current': {'P2': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'N'}, 'locked': ['P1', 'P4'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P5': 4}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 18', {'need': [['P2', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P4': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0, 'P3': 0}, 'done_s': 6})], [('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('control 49', {'need': [['P5', 'R'], ['P3', 'N'], ['P1', 'N'], ['P4', 'R'], ['P2', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P1': 0, 'P4': 3, 'P2': 5}, 'done_s': 10}), ('boundary: single supply', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': [], 'max_parallel': 1, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 5}, 'done_s': 10}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('boundary: points with individual throw times', {'need': [['P4', 'R'], ['P5', 'N']], 'current': {'P4': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P5': 3}, 'done_s': 8}), ('control 23', {'need': [['P3', 'N'], ['P4', 'N'], ['P1', 'R'], ['P6', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P4': 3, 'P5': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P6': 3}, 'done_s': 6}), ('control 26', {'need': [['P1', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P5', 'P6'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('control 29', {'need': [['P4', 'N'], ['P2', 'N'], ['P1', 'N'], ['P5', 'N'], ['P6', 'R']], 'current': {'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P2': 3, 'P3': 6, 'P4': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P1': 6}, 'done_s': 10})], [('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('boundary: nothing to move', {'need': [['P1', 'N']], 'current': {'P1': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('boundary: points with individual throw times', {'need': [['P4', 'R'], ['P5', 'N']], 'current': {'P4': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 1, 'throw_s': {'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P5': 3}, 'done_s': 8}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('control 34', {'need': [['P3', 'R']], 'current': {'P1': 'R', 'P3': 'N', 'P4': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 37', {'need': [['P5', 'R'], ['P1', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P5': 'R'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0}, 'done_s': 5}), ('control 40', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 2, 'throw_s': {'P1': 4, 'P2': 6, 'P3': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})], [('regression: long first throw then short ones', {'need': [['P1', 'R'], ['P2', 'R'], ['P3', 'R'], ['P4', 'R']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P1': 6, 'P2': 3, 'P3': 3, 'P4': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0, 'P3': 3, 'P4': 6}, 'done_s': 9}), ('control 49', {'need': [['P5', 'R'], ['P3', 'N'], ['P1', 'N'], ['P4', 'R'], ['P2', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'R', 'P4': 'N', 'P5': 'R', 'P6': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0, 'P1': 0, 'P4': 3, 'P2': 5}, 'done_s': 10}), ('boundary: locked point already in the right lie', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P2': 0}, 'done_s': 5}), ('boundary: locked point needing to move', {'need': [['P1', 'R'], ['P2', 'R']], 'current': {'P1': 'N', 'P2': 'N'}, 'locked': ['P1'], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'blocked:P1', 'starts': {}, 'done_s': 0}), ('boundary: undetected point', {'need': [['P1', 'N'], ['P2', 'R']], 'current': {'P2': 'N'}, 'locked': [], 'max_parallel': 2, 'throw_s': {}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P1': 0, 'P2': 0}, 'done_s': 5}), ('control 45', {'need': [['P5', 'N'], ['P3', 'R'], ['P2', 'R'], ['P6', 'N'], ['P4', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P2', 'P5'], 'max_parallel': 1, 'throw_s': {'P1': 6, 'P2': 4, 'P4': 6, 'P5': 3}, 'default_throw_s': 5}, {'result': 'blocked:P2', 'starts': {}, 'done_s': 0}), ('control 48', {'need': [['P3', 'R']], 'current': {'P1': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P4'], 'max_parallel': 1, 'throw_s': {'P4': 6, 'P5': 6, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P3': 0}, 'done_s': 5}), ('control 51', {'need': [['P6', 'R'], ['P5', 'N'], ['P1', 'R'], ['P4', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0})]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Points wait for a busy supply while another supply is idle sooner.

A route needs points in given lies (processed in list order). Points already detected in the needed lie are skipped; an undetected point (missing from current) must be thrown. A point that must move but is locked by another route blocks the whole request (blocked:<p>, nothing thrown). At most max_parallel points move at once: each point starts on the earliest-free supply slot (lowest index on ties) and takes its own throw time or the default. Return the start time per thrown point and the time all have finished.

split: open-access