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

N = 1
observations = []
def solve(x):
    last = None
    last_t = None
    ok_run = 0
    safe = True
    out = []
    for m in x['messages']:
        t = m['rx_ms']
        if last_t is not None and t - last_t >= x['timeout_ms']:
            safe = True
            ok_run = 0
        good = m['crc'] and 0 <= t - m['tx_ms'] <= x['max_age_ms']
        if good and last is not None:
            gap = (m['seq'] - last) % 256
            good = 1 <= gap <= 3
        if good:
            last = m['seq']
            last_t = t
            ok_run += 1
            if ok_run >= 2:
                safe = False
        else:
            ok_run = 0
        out.append([good, safe])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: timeout exactly reached', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 58', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 9, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 9, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 9, 'rx_ms': 2900, 'tx_ms': 2750, 'crc': False}, {'seq': 12, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 13, 'rx_ms': 3200, 'tx_ms': 2900, 'crc': True}, {'seq': 13, 'rx_ms': 3300, 'tx_ms': 3150, 'crc': True}, {'seq': 17, 'rx_ms': 3500, 'tx_ms': 3490, 'crc': True}, {'seq': 18, 'rx_ms': 4000, 'tx_ms': 4000, 'crc': False}, {'seq': 19, 'rx_ms': 4500, 'tx_ms': 4500, 'crc': True}]}, [[False, True], [True, True], [False, True], [True, True], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('sampled regression 66', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 254, 'rx_ms': 200, 'tx_ms': 50, 'crc': True}, {'seq': 255, 'rx_ms': 400, 'tx_ms': 101, 'crc': True}, {'seq': 0, 'rx_ms': 2900, 'tx_ms': 2601, 'crc': True}, {'seq': 1, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3200, 'tx_ms': 3050, 'crc': True}, {'seq': 6, 'rx_ms': 3700, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3900, 'tx_ms': 3599, 'crc': True}, {'seq': 6, 'rx_ms': 5100, 'tx_ms': 4799, 'crc': True}]}, [[True, True], [True, False], [True, True], [True, False], [False, False], [False, False], [False, False], [False, False]]), ('control 79', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 255, 'rx_ms': 1700, 'tx_ms': 1550, 'crc': True}, {'seq': 255, 'rx_ms': 2900, 'tx_ms': 2600, 'crc': True}, {'seq': 2, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 2, 'rx_ms': 3600, 'tx_ms': 3590, 'crc': True}, {'seq': 6, 'rx_ms': 4800, 'tx_ms': 4500, 'crc': True}, {'seq': 7, 'rx_ms': 4900, 'tx_ms': 4890, 'crc': True}, {'seq': 7, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('boundary: sequence wraps past 255', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 254, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 255, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 0, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 1', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 250, 'rx_ms': 2500, 'tx_ms': 2520, 'crc': True}, {'seq': 251, 'rx_ms': 3000, 'tx_ms': 3020, 'crc': True}, {'seq': 253, 'rx_ms': 3100, 'tx_ms': 2500, 'crc': True}, {'seq': 0, 'rx_ms': 3200, 'tx_ms': 2899, 'crc': True}, {'seq': 0, 'rx_ms': 3700, 'tx_ms': 3700, 'crc': True}]}, [[False, True], [False, True], [False, True], [False, True], [True, True]]), ('control 4', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 11, 'rx_ms': 1200, 'tx_ms': 1050, 'crc': True}, {'seq': 13, 'rx_ms': 1300, 'tx_ms': 1000, 'crc': True}, {'seq': 14, 'rx_ms': 1500, 'tx_ms': 1350, 'crc': True}, {'seq': 15, 'rx_ms': 1600, 'tx_ms': 1450, 'crc': False}, {'seq': 16, 'rx_ms': 2100, 'tx_ms': 2100, 'crc': True}, {'seq': 20, 'rx_ms': 2300, 'tx_ms': 2150, 'crc': True}, {'seq': 21, 'rx_ms': 2800, 'tx_ms': 2501, 'crc': True}, {'seq': 22, 'rx_ms': 5300, 'tx_ms': 4999, 'crc': True}, {'seq': 22, 'rx_ms': 5500, 'tx_ms': 5500, 'crc': True}]}, [[True, True], [True, False], [True, False], [False, False], [True, False], [False, False], [False, False], [False, True], [False, True]]), ('control 7', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 0, 'rx_ms': 200, 'tx_ms': 190, 'crc': False}, {'seq': 3, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}, {'seq': 3, 'rx_ms': 1500, 'tx_ms': 1200, 'crc': True}, {'seq': 3, 'rx_ms': 2700, 'tx_ms': 2400, 'crc': True}]}, [[False, True], [True, True], [False, True], [False, True]])], [('regression: timeout exactly reached', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 79', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 255, 'rx_ms': 1700, 'tx_ms': 1550, 'crc': True}, {'seq': 255, 'rx_ms': 2900, 'tx_ms': 2600, 'crc': True}, {'seq': 2, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 2, 'rx_ms': 3600, 'tx_ms': 3590, 'crc': True}, {'seq': 6, 'rx_ms': 4800, 'tx_ms': 4500, 'crc': True}, {'seq': 7, 'rx_ms': 4900, 'tx_ms': 4890, 'crc': True}, {'seq': 7, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('control 58', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 9, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 9, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 9, 'rx_ms': 2900, 'tx_ms': 2750, 'crc': False}, {'seq': 12, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 13, 'rx_ms': 3200, 'tx_ms': 2900, 'crc': True}, {'seq': 13, 'rx_ms': 3300, 'tx_ms': 3150, 'crc': True}, {'seq': 17, 'rx_ms': 3500, 'tx_ms': 3490, 'crc': True}, {'seq': 18, 'rx_ms': 4000, 'tx_ms': 4000, 'crc': False}, {'seq': 19, 'rx_ms': 4500, 'tx_ms': 4500, 'crc': True}]}, [[False, True], [True, True], [False, True], [True, True], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('boundary: duplicate telegram', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 10, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 10, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 11, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}]}, [[True, True], [False, True], [True, True]]), ('boundary: two telegrams lost', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 10, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 13, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 14, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 12', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 4, 'rx_ms': 1200, 'tx_ms': 901, 'crc': False}, {'seq': 4, 'rx_ms': 2400, 'tx_ms': 2390, 'crc': True}, {'seq': 4, 'rx_ms': 2500, 'tx_ms': 1900, 'crc': True}, {'seq': 4, 'rx_ms': 3000, 'tx_ms': 2700, 'crc': True}, {'seq': 6, 'rx_ms': 3200, 'tx_ms': 3200, 'crc': True}, {'seq': 4, 'rx_ms': 3300, 'tx_ms': 3300, 'crc': True}, {'seq': 8, 'rx_ms': 3400, 'tx_ms': 3420, 'crc': False}, {'seq': 9, 'rx_ms': 3600, 'tx_ms': 3300, 'crc': True}, {'seq': 9, 'rx_ms': 3800, 'tx_ms': 3501, 'crc': True}]}, [[False, True], [True, True], [False, True], [False, True], [True, True], [False, True], [False, True], [True, True], [False, True]]), ('control 15', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 2, 'rx_ms': 100, 'tx_ms': -200, 'crc': True}, {'seq': 6, 'rx_ms': 2600, 'tx_ms': 2600, 'crc': True}, {'seq': 6, 'rx_ms': 5100, 'tx_ms': 4801, 'crc': True}, {'seq': 6, 'rx_ms': 5200, 'tx_ms': 5050, 'crc': True}, {'seq': 6, 'rx_ms': 7700, 'tx_ms': 7550, 'crc': True}]}, [[True, True], [False, True], [False, True], [False, True], [False, True]]), ('control 18', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 251, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 252, 'rx_ms': 3000, 'tx_ms': 2701, 'crc': True}, {'seq': 254, 'rx_ms': 3500, 'tx_ms': 3199, 'crc': True}, {'seq': 254, 'rx_ms': 4000, 'tx_ms': 4020, 'crc': True}, {'seq': 0, 'rx_ms': 4500, 'tx_ms': 4201, 'crc': True}, {'seq': 0, 'rx_ms': 5000, 'tx_ms': 4400, 'crc': True}, {'seq': 4, 'rx_ms': 7500, 'tx_ms': 7199, 'crc': True}]}, [[True, True], [True, True], [False, True], [False, True], [False, True], [False, True], [False, True]])], [('regression: timeout exactly reached', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 58', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 9, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 9, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 9, 'rx_ms': 2900, 'tx_ms': 2750, 'crc': False}, {'seq': 12, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 13, 'rx_ms': 3200, 'tx_ms': 2900, 'crc': True}, {'seq': 13, 'rx_ms': 3300, 'tx_ms': 3150, 'crc': True}, {'seq': 17, 'rx_ms': 3500, 'tx_ms': 3490, 'crc': True}, {'seq': 18, 'rx_ms': 4000, 'tx_ms': 4000, 'crc': False}, {'seq': 19, 'rx_ms': 4500, 'tx_ms': 4500, 'crc': True}]}, [[False, True], [True, True], [False, True], [True, True], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('sampled regression 66', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 254, 'rx_ms': 200, 'tx_ms': 50, 'crc': True}, {'seq': 255, 'rx_ms': 400, 'tx_ms': 101, 'crc': True}, {'seq': 0, 'rx_ms': 2900, 'tx_ms': 2601, 'crc': True}, {'seq': 1, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3200, 'tx_ms': 3050, 'crc': True}, {'seq': 6, 'rx_ms': 3700, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3900, 'tx_ms': 3599, 'crc': True}, {'seq': 6, 'rx_ms': 5100, 'tx_ms': 4799, 'crc': True}]}, [[True, True], [True, False], [True, True], [True, False], [False, False], [False, False], [False, False], [False, False]]), ('control 79', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 255, 'rx_ms': 1700, 'tx_ms': 1550, 'crc': True}, {'seq': 255, 'rx_ms': 2900, 'tx_ms': 2600, 'crc': True}, {'seq': 2, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 2, 'rx_ms': 3600, 'tx_ms': 3590, 'crc': True}, {'seq': 6, 'rx_ms': 4800, 'tx_ms': 4500, 'crc': True}, {'seq': 7, 'rx_ms': 4900, 'tx_ms': 4890, 'crc': True}, {'seq': 7, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('boundary: telegram from the future', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 10, 'rx_ms': 100, 'tx_ms': 150, 'crc': True}, {'seq': 11, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 12, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}]}, [[False, True], [True, True], [True, False]]), ('control 23', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 250, 'rx_ms': 2500, 'tx_ms': 2199, 'crc': True}, {'seq': 254, 'rx_ms': 3700, 'tx_ms': 3401, 'crc': True}, {'seq': 254, 'rx_ms': 3800, 'tx_ms': 3650, 'crc': True}, {'seq': 254, 'rx_ms': 4000, 'tx_ms': 3699, 'crc': True}, {'seq': 254, 'rx_ms': 6500, 'tx_ms': 6350, 'crc': True}, {'seq': 255, 'rx_ms': 6600, 'tx_ms': 6299, 'crc': True}, {'seq': 255, 'rx_ms': 9100, 'tx_ms': 9120, 'crc': True}, {'seq': 0, 'rx_ms': 11600, 'tx_ms': 11000, 'crc': True}, {'seq': 255, 'rx_ms': 12800, 'tx_ms': 12800, 'crc': True}]}, [[False, True], [True, True], [False, True], [False, True], [False, True], [False, True], [False, True], [False, True], [True, True]]), ('control 26', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 253, 'rx_ms': 2400, 'tx_ms': 2250, 'crc': True}, {'seq': 254, 'rx_ms': 2900, 'tx_ms': 2890, 'crc': True}, {'seq': 254, 'rx_ms': 4100, 'tx_ms': 4090, 'crc': True}, {'seq': 253, 'rx_ms': 5300, 'tx_ms': 5290, 'crc': True}, {'seq': 0, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}, {'seq': 1, 'rx_ms': 5500, 'tx_ms': 5201, 'crc': True}, {'seq': 3, 'rx_ms': 5600, 'tx_ms': 5000, 'crc': False}, {'seq': 2, 'rx_ms': 5700, 'tx_ms': 5720, 'crc': False}, {'seq': 3, 'rx_ms': 5800, 'tx_ms': 5501, 'crc': True}]}, [[False, True], [True, True], [True, False], [False, True], [False, True], [True, True], [True, False], [False, False], [False, False], [True, False]]), ('control 29', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 255, 'rx_ms': 500, 'tx_ms': -100, 'crc': True}, {'seq': 3, 'rx_ms': 600, 'tx_ms': 600, 'crc': True}, {'seq': 6, 'rx_ms': 3100, 'tx_ms': 3090, 'crc': True}]}, [[False, True], [True, True], [True, True]])], [('regression: timeout exactly reached', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 79', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 255, 'rx_ms': 1700, 'tx_ms': 1550, 'crc': True}, {'seq': 255, 'rx_ms': 2900, 'tx_ms': 2600, 'crc': True}, {'seq': 2, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 2, 'rx_ms': 3600, 'tx_ms': 3590, 'crc': True}, {'seq': 6, 'rx_ms': 4800, 'tx_ms': 4500, 'crc': True}, {'seq': 7, 'rx_ms': 4900, 'tx_ms': 4890, 'crc': True}, {'seq': 7, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('control 58', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 9, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 9, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 9, 'rx_ms': 2900, 'tx_ms': 2750, 'crc': False}, {'seq': 12, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 13, 'rx_ms': 3200, 'tx_ms': 2900, 'crc': True}, {'seq': 13, 'rx_ms': 3300, 'tx_ms': 3150, 'crc': True}, {'seq': 17, 'rx_ms': 3500, 'tx_ms': 3490, 'crc': True}, {'seq': 18, 'rx_ms': 4000, 'tx_ms': 4000, 'crc': False}, {'seq': 19, 'rx_ms': 4500, 'tx_ms': 4500, 'crc': True}]}, [[False, True], [True, True], [False, True], [True, True], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('boundary: corrupt telegram between good ones', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': False}, {'seq': 3, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}, {'seq': 4, 'rx_ms': 400, 'tx_ms': 390, 'crc': True}]}, [[True, True], [False, True], [True, True], [True, False]]), ('boundary: silence then recovery', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1300, 'tx_ms': 1290, 'crc': True}, {'seq': 4, 'rx_ms': 1400, 'tx_ms': 1390, 'crc': True}]}, [[True, True], [True, False], [True, True], [True, False]]), ('control 34', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 255, 'rx_ms': 1200, 'tx_ms': 901, 'crc': False}, {'seq': 1, 'rx_ms': 1700, 'tx_ms': 1400, 'crc': True}, {'seq': 1, 'rx_ms': 4200, 'tx_ms': 4050, 'crc': True}, {'seq': 2, 'rx_ms': 4300, 'tx_ms': 4320, 'crc': True}]}, [[False, True], [True, True], [False, True], [False, True]]), ('control 37', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 251, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 252, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 252, 'rx_ms': 2900, 'tx_ms': 2890, 'crc': True}, {'seq': 252, 'rx_ms': 3000, 'tx_ms': 3000, 'crc': True}, {'seq': 253, 'rx_ms': 3100, 'tx_ms': 2800, 'crc': True}, {'seq': 255, 'rx_ms': 4300, 'tx_ms': 4320, 'crc': True}]}, [[False, True], [True, True], [False, True], [False, True], [True, True], [False, True]]), ('control 40', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 254, 'rx_ms': 1200, 'tx_ms': 600, 'crc': True}, {'seq': 254, 'rx_ms': 2400, 'tx_ms': 2100, 'crc': True}, {'seq': 254, 'rx_ms': 2500, 'tx_ms': 2490, 'crc': False}]}, [[False, True], [True, True], [False, True]])], [('regression: timeout exactly reached', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 58', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 9, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 9, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 9, 'rx_ms': 2900, 'tx_ms': 2750, 'crc': False}, {'seq': 12, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 13, 'rx_ms': 3200, 'tx_ms': 2900, 'crc': True}, {'seq': 13, 'rx_ms': 3300, 'tx_ms': 3150, 'crc': True}, {'seq': 17, 'rx_ms': 3500, 'tx_ms': 3490, 'crc': True}, {'seq': 18, 'rx_ms': 4000, 'tx_ms': 4000, 'crc': False}, {'seq': 19, 'rx_ms': 4500, 'tx_ms': 4500, 'crc': True}]}, [[False, True], [True, True], [False, True], [True, True], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('sampled regression 66', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 254, 'rx_ms': 200, 'tx_ms': 50, 'crc': True}, {'seq': 255, 'rx_ms': 400, 'tx_ms': 101, 'crc': True}, {'seq': 0, 'rx_ms': 2900, 'tx_ms': 2601, 'crc': True}, {'seq': 1, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3200, 'tx_ms': 3050, 'crc': True}, {'seq': 6, 'rx_ms': 3700, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3900, 'tx_ms': 3599, 'crc': True}, {'seq': 6, 'rx_ms': 5100, 'tx_ms': 4799, 'crc': True}]}, [[True, True], [True, False], [True, True], [True, False], [False, False], [False, False], [False, False], [False, False]]), ('control 79', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 255, 'rx_ms': 1700, 'tx_ms': 1550, 'crc': True}, {'seq': 255, 'rx_ms': 2900, 'tx_ms': 2600, 'crc': True}, {'seq': 2, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 2, 'rx_ms': 3600, 'tx_ms': 3590, 'crc': True}, {'seq': 6, 'rx_ms': 4800, 'tx_ms': 4500, 'crc': True}, {'seq': 7, 'rx_ms': 4900, 'tx_ms': 4890, 'crc': True}, {'seq': 7, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('boundary: bad telegrams keep the link alive', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 9, 'rx_ms': 800, 'tx_ms': 790, 'crc': True}, {'seq': 3, 'rx_ms': 1100, 'tx_ms': 1090, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False]]), ('control 45', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 13, 'rx_ms': 200, 'tx_ms': -100, 'crc': True}, {'seq': 14, 'rx_ms': 300, 'tx_ms': -1, 'crc': True}, {'seq': 18, 'rx_ms': 500, 'tx_ms': 201, 'crc': False}, {'seq': 19, 'rx_ms': 3000, 'tx_ms': 3020, 'crc': True}, {'seq': 17, 'rx_ms': 5500, 'tx_ms': 4900, 'crc': True}, {'seq': 16, 'rx_ms': 5700, 'tx_ms': 5401, 'crc': True}]}, [[True, True], [False, True], [False, True], [False, True], [False, True], [True, True]]), ('control 48', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 253, 'rx_ms': 1200, 'tx_ms': 600, 'crc': True}, {'seq': 253, 'rx_ms': 2400, 'tx_ms': 2420, 'crc': True}, {'seq': 254, 'rx_ms': 4900, 'tx_ms': 4300, 'crc': True}, {'seq': 2, 'rx_ms': 5400, 'tx_ms': 5420, 'crc': True}, {'seq': 6, 'rx_ms': 5900, 'tx_ms': 5300, 'crc': True}, {'seq': 6, 'rx_ms': 6000, 'tx_ms': 5400, 'crc': True}, {'seq': 6, 'rx_ms': 8500, 'tx_ms': 8500, 'crc': True}, {'seq': 5, 'rx_ms': 8600, 'tx_ms': 8590, 'crc': True}]}, [[False, True], [False, True], [False, True], [False, True], [False, True], [False, True], [True, True], [False, True]]), ('control 51', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 251, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}, {'seq': 252, 'rx_ms': 1400, 'tx_ms': 1099, 'crc': True}, {'seq': 253, 'rx_ms': 1900, 'tx_ms': 1920, 'crc': True}, {'seq': 253, 'rx_ms': 2400, 'tx_ms': 2400, 'crc': True}, {'seq': 254, 'rx_ms': 2600, 'tx_ms': 2301, 'crc': True}, {'seq': 0, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 2, 'rx_ms': 3300, 'tx_ms': 2999, 'crc': True}, {'seq': 3, 'rx_ms': 5800, 'tx_ms': 5499, 'crc': True}, {'seq': 4, 'rx_ms': 5900, 'tx_ms': 5601, 'crc': True}, {'seq': 5, 'rx_ms': 6000, 'tx_ms': 6020, 'crc': False}]}, [[True, True], [False, True], [False, True], [True, True], [True, False], [True, False], [False, False], [False, True], [False, True], [False, True]])]]
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):
    last = None
    last_t = None
    ok_run = 0
    safe = True
    out = []
    for m in x['messages']:
        t = m['rx_ms']
        if last_t is not None and t - last_t > x['timeout_ms']:
            safe = True
            ok_run = 0
        last_t = t
        good = m['crc'] and 0 <= t - m['tx_ms'] <= x['max_age_ms']
        if good and last is not None:
            gap = (m['seq'] - last) % 256
            good = 1 <= gap <= 3
        if good:
            last = m['seq']
            ok_run += 1
            if ok_run >= 2:
                safe = False
        else:
            ok_run = 0
        out.append([good, safe])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: timeout exactly reached', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 58', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 9, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 9, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 9, 'rx_ms': 2900, 'tx_ms': 2750, 'crc': False}, {'seq': 12, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 13, 'rx_ms': 3200, 'tx_ms': 2900, 'crc': True}, {'seq': 13, 'rx_ms': 3300, 'tx_ms': 3150, 'crc': True}, {'seq': 17, 'rx_ms': 3500, 'tx_ms': 3490, 'crc': True}, {'seq': 18, 'rx_ms': 4000, 'tx_ms': 4000, 'crc': False}, {'seq': 19, 'rx_ms': 4500, 'tx_ms': 4500, 'crc': True}]}, [[False, True], [True, True], [False, True], [True, True], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('sampled regression 66', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 254, 'rx_ms': 200, 'tx_ms': 50, 'crc': True}, {'seq': 255, 'rx_ms': 400, 'tx_ms': 101, 'crc': True}, {'seq': 0, 'rx_ms': 2900, 'tx_ms': 2601, 'crc': True}, {'seq': 1, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3200, 'tx_ms': 3050, 'crc': True}, {'seq': 6, 'rx_ms': 3700, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3900, 'tx_ms': 3599, 'crc': True}, {'seq': 6, 'rx_ms': 5100, 'tx_ms': 4799, 'crc': True}]}, [[True, True], [True, False], [True, True], [True, False], [False, False], [False, False], [False, False], [False, False]]), ('control 79', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 255, 'rx_ms': 1700, 'tx_ms': 1550, 'crc': True}, {'seq': 255, 'rx_ms': 2900, 'tx_ms': 2600, 'crc': True}, {'seq': 2, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 2, 'rx_ms': 3600, 'tx_ms': 3590, 'crc': True}, {'seq': 6, 'rx_ms': 4800, 'tx_ms': 4500, 'crc': True}, {'seq': 7, 'rx_ms': 4900, 'tx_ms': 4890, 'crc': True}, {'seq': 7, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('boundary: sequence wraps past 255', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 254, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 255, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 0, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 1', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 250, 'rx_ms': 2500, 'tx_ms': 2520, 'crc': True}, {'seq': 251, 'rx_ms': 3000, 'tx_ms': 3020, 'crc': True}, {'seq': 253, 'rx_ms': 3100, 'tx_ms': 2500, 'crc': True}, {'seq': 0, 'rx_ms': 3200, 'tx_ms': 2899, 'crc': True}, {'seq': 0, 'rx_ms': 3700, 'tx_ms': 3700, 'crc': True}]}, [[False, True], [False, True], [False, True], [False, True], [True, True]]), ('control 4', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 11, 'rx_ms': 1200, 'tx_ms': 1050, 'crc': True}, {'seq': 13, 'rx_ms': 1300, 'tx_ms': 1000, 'crc': True}, {'seq': 14, 'rx_ms': 1500, 'tx_ms': 1350, 'crc': True}, {'seq': 15, 'rx_ms': 1600, 'tx_ms': 1450, 'crc': False}, {'seq': 16, 'rx_ms': 2100, 'tx_ms': 2100, 'crc': True}, {'seq': 20, 'rx_ms': 2300, 'tx_ms': 2150, 'crc': True}, {'seq': 21, 'rx_ms': 2800, 'tx_ms': 2501, 'crc': True}, {'seq': 22, 'rx_ms': 5300, 'tx_ms': 4999, 'crc': True}, {'seq': 22, 'rx_ms': 5500, 'tx_ms': 5500, 'crc': True}]}, [[True, True], [True, False], [True, False], [False, False], [True, False], [False, False], [False, False], [False, True], [False, True]]), ('control 7', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 0, 'rx_ms': 200, 'tx_ms': 190, 'crc': False}, {'seq': 3, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}, {'seq': 3, 'rx_ms': 1500, 'tx_ms': 1200, 'crc': True}, {'seq': 3, 'rx_ms': 2700, 'tx_ms': 2400, 'crc': True}]}, [[False, True], [True, True], [False, True], [False, True]])], [('regression: timeout exactly reached', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 79', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 255, 'rx_ms': 1700, 'tx_ms': 1550, 'crc': True}, {'seq': 255, 'rx_ms': 2900, 'tx_ms': 2600, 'crc': True}, {'seq': 2, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 2, 'rx_ms': 3600, 'tx_ms': 3590, 'crc': True}, {'seq': 6, 'rx_ms': 4800, 'tx_ms': 4500, 'crc': True}, {'seq': 7, 'rx_ms': 4900, 'tx_ms': 4890, 'crc': True}, {'seq': 7, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('control 58', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 9, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 9, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 9, 'rx_ms': 2900, 'tx_ms': 2750, 'crc': False}, {'seq': 12, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 13, 'rx_ms': 3200, 'tx_ms': 2900, 'crc': True}, {'seq': 13, 'rx_ms': 3300, 'tx_ms': 3150, 'crc': True}, {'seq': 17, 'rx_ms': 3500, 'tx_ms': 3490, 'crc': True}, {'seq': 18, 'rx_ms': 4000, 'tx_ms': 4000, 'crc': False}, {'seq': 19, 'rx_ms': 4500, 'tx_ms': 4500, 'crc': True}]}, [[False, True], [True, True], [False, True], [True, True], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('boundary: duplicate telegram', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 10, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 10, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 11, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}]}, [[True, True], [False, True], [True, True]]), ('boundary: two telegrams lost', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 10, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 13, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 14, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 12', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 4, 'rx_ms': 1200, 'tx_ms': 901, 'crc': False}, {'seq': 4, 'rx_ms': 2400, 'tx_ms': 2390, 'crc': True}, {'seq': 4, 'rx_ms': 2500, 'tx_ms': 1900, 'crc': True}, {'seq': 4, 'rx_ms': 3000, 'tx_ms': 2700, 'crc': True}, {'seq': 6, 'rx_ms': 3200, 'tx_ms': 3200, 'crc': True}, {'seq': 4, 'rx_ms': 3300, 'tx_ms': 3300, 'crc': True}, {'seq': 8, 'rx_ms': 3400, 'tx_ms': 3420, 'crc': False}, {'seq': 9, 'rx_ms': 3600, 'tx_ms': 3300, 'crc': True}, {'seq': 9, 'rx_ms': 3800, 'tx_ms': 3501, 'crc': True}]}, [[False, True], [True, True], [False, True], [False, True], [True, True], [False, True], [False, True], [True, True], [False, True]]), ('control 15', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 2, 'rx_ms': 100, 'tx_ms': -200, 'crc': True}, {'seq': 6, 'rx_ms': 2600, 'tx_ms': 2600, 'crc': True}, {'seq': 6, 'rx_ms': 5100, 'tx_ms': 4801, 'crc': True}, {'seq': 6, 'rx_ms': 5200, 'tx_ms': 5050, 'crc': True}, {'seq': 6, 'rx_ms': 7700, 'tx_ms': 7550, 'crc': True}]}, [[True, True], [False, True], [False, True], [False, True], [False, True]]), ('control 18', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 251, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 252, 'rx_ms': 3000, 'tx_ms': 2701, 'crc': True}, {'seq': 254, 'rx_ms': 3500, 'tx_ms': 3199, 'crc': True}, {'seq': 254, 'rx_ms': 4000, 'tx_ms': 4020, 'crc': True}, {'seq': 0, 'rx_ms': 4500, 'tx_ms': 4201, 'crc': True}, {'seq': 0, 'rx_ms': 5000, 'tx_ms': 4400, 'crc': True}, {'seq': 4, 'rx_ms': 7500, 'tx_ms': 7199, 'crc': True}]}, [[True, True], [True, True], [False, True], [False, True], [False, True], [False, True], [False, True]])], [('regression: timeout exactly reached', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 58', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 9, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 9, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 9, 'rx_ms': 2900, 'tx_ms': 2750, 'crc': False}, {'seq': 12, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 13, 'rx_ms': 3200, 'tx_ms': 2900, 'crc': True}, {'seq': 13, 'rx_ms': 3300, 'tx_ms': 3150, 'crc': True}, {'seq': 17, 'rx_ms': 3500, 'tx_ms': 3490, 'crc': True}, {'seq': 18, 'rx_ms': 4000, 'tx_ms': 4000, 'crc': False}, {'seq': 19, 'rx_ms': 4500, 'tx_ms': 4500, 'crc': True}]}, [[False, True], [True, True], [False, True], [True, True], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('sampled regression 66', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 254, 'rx_ms': 200, 'tx_ms': 50, 'crc': True}, {'seq': 255, 'rx_ms': 400, 'tx_ms': 101, 'crc': True}, {'seq': 0, 'rx_ms': 2900, 'tx_ms': 2601, 'crc': True}, {'seq': 1, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3200, 'tx_ms': 3050, 'crc': True}, {'seq': 6, 'rx_ms': 3700, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3900, 'tx_ms': 3599, 'crc': True}, {'seq': 6, 'rx_ms': 5100, 'tx_ms': 4799, 'crc': True}]}, [[True, True], [True, False], [True, True], [True, False], [False, False], [False, False], [False, False], [False, False]]), ('control 79', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 255, 'rx_ms': 1700, 'tx_ms': 1550, 'crc': True}, {'seq': 255, 'rx_ms': 2900, 'tx_ms': 2600, 'crc': True}, {'seq': 2, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 2, 'rx_ms': 3600, 'tx_ms': 3590, 'crc': True}, {'seq': 6, 'rx_ms': 4800, 'tx_ms': 4500, 'crc': True}, {'seq': 7, 'rx_ms': 4900, 'tx_ms': 4890, 'crc': True}, {'seq': 7, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('boundary: telegram from the future', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 10, 'rx_ms': 100, 'tx_ms': 150, 'crc': True}, {'seq': 11, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 12, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}]}, [[False, True], [True, True], [True, False]]), ('control 23', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 250, 'rx_ms': 2500, 'tx_ms': 2199, 'crc': True}, {'seq': 254, 'rx_ms': 3700, 'tx_ms': 3401, 'crc': True}, {'seq': 254, 'rx_ms': 3800, 'tx_ms': 3650, 'crc': True}, {'seq': 254, 'rx_ms': 4000, 'tx_ms': 3699, 'crc': True}, {'seq': 254, 'rx_ms': 6500, 'tx_ms': 6350, 'crc': True}, {'seq': 255, 'rx_ms': 6600, 'tx_ms': 6299, 'crc': True}, {'seq': 255, 'rx_ms': 9100, 'tx_ms': 9120, 'crc': True}, {'seq': 0, 'rx_ms': 11600, 'tx_ms': 11000, 'crc': True}, {'seq': 255, 'rx_ms': 12800, 'tx_ms': 12800, 'crc': True}]}, [[False, True], [True, True], [False, True], [False, True], [False, True], [False, True], [False, True], [False, True], [True, True]]), ('control 26', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 253, 'rx_ms': 2400, 'tx_ms': 2250, 'crc': True}, {'seq': 254, 'rx_ms': 2900, 'tx_ms': 2890, 'crc': True}, {'seq': 254, 'rx_ms': 4100, 'tx_ms': 4090, 'crc': True}, {'seq': 253, 'rx_ms': 5300, 'tx_ms': 5290, 'crc': True}, {'seq': 0, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}, {'seq': 1, 'rx_ms': 5500, 'tx_ms': 5201, 'crc': True}, {'seq': 3, 'rx_ms': 5600, 'tx_ms': 5000, 'crc': False}, {'seq': 2, 'rx_ms': 5700, 'tx_ms': 5720, 'crc': False}, {'seq': 3, 'rx_ms': 5800, 'tx_ms': 5501, 'crc': True}]}, [[False, True], [True, True], [True, False], [False, True], [False, True], [True, True], [True, False], [False, False], [False, False], [True, False]]), ('control 29', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 255, 'rx_ms': 500, 'tx_ms': -100, 'crc': True}, {'seq': 3, 'rx_ms': 600, 'tx_ms': 600, 'crc': True}, {'seq': 6, 'rx_ms': 3100, 'tx_ms': 3090, 'crc': True}]}, [[False, True], [True, True], [True, True]])], [('regression: timeout exactly reached', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 79', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 255, 'rx_ms': 1700, 'tx_ms': 1550, 'crc': True}, {'seq': 255, 'rx_ms': 2900, 'tx_ms': 2600, 'crc': True}, {'seq': 2, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 2, 'rx_ms': 3600, 'tx_ms': 3590, 'crc': True}, {'seq': 6, 'rx_ms': 4800, 'tx_ms': 4500, 'crc': True}, {'seq': 7, 'rx_ms': 4900, 'tx_ms': 4890, 'crc': True}, {'seq': 7, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('control 58', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 9, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 9, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 9, 'rx_ms': 2900, 'tx_ms': 2750, 'crc': False}, {'seq': 12, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 13, 'rx_ms': 3200, 'tx_ms': 2900, 'crc': True}, {'seq': 13, 'rx_ms': 3300, 'tx_ms': 3150, 'crc': True}, {'seq': 17, 'rx_ms': 3500, 'tx_ms': 3490, 'crc': True}, {'seq': 18, 'rx_ms': 4000, 'tx_ms': 4000, 'crc': False}, {'seq': 19, 'rx_ms': 4500, 'tx_ms': 4500, 'crc': True}]}, [[False, True], [True, True], [False, True], [True, True], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('boundary: corrupt telegram between good ones', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': False}, {'seq': 3, 'rx_ms': 300, 'tx_ms': 290, 'crc': True}, {'seq': 4, 'rx_ms': 400, 'tx_ms': 390, 'crc': True}]}, [[True, True], [False, True], [True, True], [True, False]]), ('boundary: silence then recovery', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1300, 'tx_ms': 1290, 'crc': True}, {'seq': 4, 'rx_ms': 1400, 'tx_ms': 1390, 'crc': True}]}, [[True, True], [True, False], [True, True], [True, False]]), ('control 34', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 255, 'rx_ms': 1200, 'tx_ms': 901, 'crc': False}, {'seq': 1, 'rx_ms': 1700, 'tx_ms': 1400, 'crc': True}, {'seq': 1, 'rx_ms': 4200, 'tx_ms': 4050, 'crc': True}, {'seq': 2, 'rx_ms': 4300, 'tx_ms': 4320, 'crc': True}]}, [[False, True], [True, True], [False, True], [False, True]]), ('control 37', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 251, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 252, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 252, 'rx_ms': 2900, 'tx_ms': 2890, 'crc': True}, {'seq': 252, 'rx_ms': 3000, 'tx_ms': 3000, 'crc': True}, {'seq': 253, 'rx_ms': 3100, 'tx_ms': 2800, 'crc': True}, {'seq': 255, 'rx_ms': 4300, 'tx_ms': 4320, 'crc': True}]}, [[False, True], [True, True], [False, True], [False, True], [True, True], [False, True]]), ('control 40', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 254, 'rx_ms': 1200, 'tx_ms': 600, 'crc': True}, {'seq': 254, 'rx_ms': 2400, 'tx_ms': 2100, 'crc': True}, {'seq': 254, 'rx_ms': 2500, 'tx_ms': 2490, 'crc': False}]}, [[False, True], [True, True], [False, True]])], [('regression: timeout exactly reached', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 3, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}]}, [[True, True], [True, False], [True, False]]), ('control 58', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 9, 'rx_ms': 1200, 'tx_ms': 899, 'crc': True}, {'seq': 9, 'rx_ms': 1700, 'tx_ms': 1700, 'crc': True}, {'seq': 9, 'rx_ms': 2900, 'tx_ms': 2750, 'crc': False}, {'seq': 12, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 13, 'rx_ms': 3200, 'tx_ms': 2900, 'crc': True}, {'seq': 13, 'rx_ms': 3300, 'tx_ms': 3150, 'crc': True}, {'seq': 17, 'rx_ms': 3500, 'tx_ms': 3490, 'crc': True}, {'seq': 18, 'rx_ms': 4000, 'tx_ms': 4000, 'crc': False}, {'seq': 19, 'rx_ms': 4500, 'tx_ms': 4500, 'crc': True}]}, [[False, True], [True, True], [False, True], [True, True], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('sampled regression 66', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 254, 'rx_ms': 200, 'tx_ms': 50, 'crc': True}, {'seq': 255, 'rx_ms': 400, 'tx_ms': 101, 'crc': True}, {'seq': 0, 'rx_ms': 2900, 'tx_ms': 2601, 'crc': True}, {'seq': 1, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3200, 'tx_ms': 3050, 'crc': True}, {'seq': 6, 'rx_ms': 3700, 'tx_ms': 3100, 'crc': True}, {'seq': 5, 'rx_ms': 3900, 'tx_ms': 3599, 'crc': True}, {'seq': 6, 'rx_ms': 5100, 'tx_ms': 4799, 'crc': True}]}, [[True, True], [True, False], [True, True], [True, False], [False, False], [False, False], [False, False], [False, False]]), ('control 79', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 252, 'rx_ms': 500, 'tx_ms': 201, 'crc': True}, {'seq': 255, 'rx_ms': 1700, 'tx_ms': 1550, 'crc': True}, {'seq': 255, 'rx_ms': 2900, 'tx_ms': 2600, 'crc': True}, {'seq': 2, 'rx_ms': 3100, 'tx_ms': 3100, 'crc': True}, {'seq': 2, 'rx_ms': 3600, 'tx_ms': 3590, 'crc': True}, {'seq': 6, 'rx_ms': 4800, 'tx_ms': 4500, 'crc': True}, {'seq': 7, 'rx_ms': 4900, 'tx_ms': 4890, 'crc': True}, {'seq': 7, 'rx_ms': 5400, 'tx_ms': 5390, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False], [False, False], [False, False], [False, False], [False, True]]), ('boundary: bad telegrams keep the link alive', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 1, 'rx_ms': 100, 'tx_ms': 90, 'crc': True}, {'seq': 2, 'rx_ms': 200, 'tx_ms': 190, 'crc': True}, {'seq': 9, 'rx_ms': 800, 'tx_ms': 790, 'crc': True}, {'seq': 3, 'rx_ms': 1100, 'tx_ms': 1090, 'crc': True}]}, [[True, True], [True, False], [False, False], [True, False]]), ('control 45', {'timeout_ms': 2000, 'max_age_ms': 300, 'messages': [{'seq': 13, 'rx_ms': 200, 'tx_ms': -100, 'crc': True}, {'seq': 14, 'rx_ms': 300, 'tx_ms': -1, 'crc': True}, {'seq': 18, 'rx_ms': 500, 'tx_ms': 201, 'crc': False}, {'seq': 19, 'rx_ms': 3000, 'tx_ms': 3020, 'crc': True}, {'seq': 17, 'rx_ms': 5500, 'tx_ms': 4900, 'crc': True}, {'seq': 16, 'rx_ms': 5700, 'tx_ms': 5401, 'crc': True}]}, [[True, True], [False, True], [False, True], [False, True], [False, True], [True, True]]), ('control 48', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 253, 'rx_ms': 1200, 'tx_ms': 600, 'crc': True}, {'seq': 253, 'rx_ms': 2400, 'tx_ms': 2420, 'crc': True}, {'seq': 254, 'rx_ms': 4900, 'tx_ms': 4300, 'crc': True}, {'seq': 2, 'rx_ms': 5400, 'tx_ms': 5420, 'crc': True}, {'seq': 6, 'rx_ms': 5900, 'tx_ms': 5300, 'crc': True}, {'seq': 6, 'rx_ms': 6000, 'tx_ms': 5400, 'crc': True}, {'seq': 6, 'rx_ms': 8500, 'tx_ms': 8500, 'crc': True}, {'seq': 5, 'rx_ms': 8600, 'tx_ms': 8590, 'crc': True}]}, [[False, True], [False, True], [False, True], [False, True], [False, True], [False, True], [True, True], [False, True]]), ('control 51', {'timeout_ms': 1000, 'max_age_ms': 300, 'messages': [{'seq': 251, 'rx_ms': 1200, 'tx_ms': 1190, 'crc': True}, {'seq': 252, 'rx_ms': 1400, 'tx_ms': 1099, 'crc': True}, {'seq': 253, 'rx_ms': 1900, 'tx_ms': 1920, 'crc': True}, {'seq': 253, 'rx_ms': 2400, 'tx_ms': 2400, 'crc': True}, {'seq': 254, 'rx_ms': 2600, 'tx_ms': 2301, 'crc': True}, {'seq': 0, 'rx_ms': 3100, 'tx_ms': 2801, 'crc': True}, {'seq': 2, 'rx_ms': 3300, 'tx_ms': 2999, 'crc': True}, {'seq': 3, 'rx_ms': 5800, 'tx_ms': 5499, 'crc': True}, {'seq': 4, 'rx_ms': 5900, 'tx_ms': 5601, 'crc': True}, {'seq': 5, 'rx_ms': 6000, 'tx_ms': 6020, 'crc': False}]}, [[True, True], [False, True], [False, True], [True, True], [True, False], [True, False], [False, False], [False, True], [False, True], [False, True]])]]
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 link times out on an exact timeout gap, or never times out while only garbage arrives.

Telegrams carry an 8-bit sequence number, send and receive times and a CRC flag. A telegram is good if its CRC is valid, 0 <= rx-tx <= max_age_ms and (after the first good one) its sequence advances by 1..3 modulo 256. The link starts in safe state; if more than timeout_ms passes between the last good telegram and a new arrival the link falls back to safe state. Two consecutive good telegrams leave safe state; any bad telegram resets that run. Output [good, safe] per telegram.

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 in locked:
            return {'result': 'blocked:' + p, 'starts': {}, 'done_s': 0}
        if cur.get(p) == pos:
            continue
        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: 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}), ('sampled regression 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 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: 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: 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}), ('sampled regression 36', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P3': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P5'], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('sampled regression 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}), ('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 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: 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}), ('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}), ('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}), ('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: 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 43', {'need': [['P1', 'R'], ['P6', 'R'], ['P4', 'R'], ['P3', 'N'], ['P5', 'R']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P6': 'N'}, 'locked': ['P5'], 'max_parallel': 1, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 6}, 'default_throw_s': 5}, {'result': 'blocked:P5', '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: 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}), ('sampled regression 74', {'need': [['P6', 'N'], ['P3', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P4': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0}, 'done_s': 3}), ('control 73', {'need': [['P6', 'N'], ['P5', 'R'], ['P4', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P3', 'P4', 'P5'], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 3, 'P5': 6}, 'default_throw_s': 5}, {'result': 'blocked:P5', '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}), ('sampled regression 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:
            continue
        if p in locked:
            continue
        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: 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}), ('sampled regression 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 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: 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: 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}), ('sampled regression 36', {'need': [['P5', 'N']], 'current': {'P1': 'R', 'P3': 'R', 'P5': 'N', 'P6': 'R'}, 'locked': ['P5'], 'max_parallel': 1, 'throw_s': {'P1': 4, 'P3': 6, 'P4': 6, 'P5': 6}, 'default_throw_s': 5}, {'result': 'set', 'starts': {}, 'done_s': 0}), ('sampled regression 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}), ('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 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: 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}), ('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}), ('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}), ('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: 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 43', {'need': [['P1', 'R'], ['P6', 'R'], ['P4', 'R'], ['P3', 'N'], ['P5', 'R']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P6': 'N'}, 'locked': ['P5'], 'max_parallel': 1, 'throw_s': {'P3': 3, 'P5': 4, 'P6': 6}, 'default_throw_s': 5}, {'result': 'blocked:P5', '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: 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}), ('sampled regression 74', {'need': [['P6', 'N'], ['P3', 'N']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P3'], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P4': 4, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0}, 'done_s': 3}), ('control 73', {'need': [['P6', 'N'], ['P5', 'R'], ['P4', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1', 'P3', 'P4', 'P5'], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P2': 3, 'P4': 3, 'P5': 6}, 'default_throw_s': 5}, {'result': 'blocked:P5', '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}), ('sampled regression 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 route sharing a point in the same lie with another route is refused.

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 = min(range(len(slots)), key=lambda i: (slots[i], i))
        starts[p] = slots[k]
        slots[k] += 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: 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: 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: 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 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 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}), ('sampled regression 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: 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}), ('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}), ('control 2', {'need': [['P4', 'R'], ['P6', 'R'], ['P5', 'R'], ['P2', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1'], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P3': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0, 'P5': 0, 'P2': 0}, 'done_s': 5}), ('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 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: 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}), ('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 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}), ('control 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}), ('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 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 32', {'need': [['P2', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P5', 'P6'], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 6}, '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 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}), ('sampled regression 27', {'need': [['P4', 'R'], ['P2', 'R'], ['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'N'}, 'locked': ['P3'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4, 'P4': 3, 'P5': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P2': 3, 'P6': 6}, 'done_s': 11}), ('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: 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: 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}), ('sampled regression 65', {'need': [['P6', 'N']], 'current': {'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 4, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0}, 'done_s': 3}), ('control 39', {'need': [['P4', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': ['P2'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 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}), ('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'].get(p, 0)
    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: 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: 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: 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 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 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}), ('sampled regression 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: 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}), ('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}), ('control 2', {'need': [['P4', 'R'], ['P6', 'R'], ['P5', 'R'], ['P2', 'N']], 'current': {'P1': 'N', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'N', 'P6': 'N'}, 'locked': ['P1'], 'max_parallel': 3, 'throw_s': {'P1': 6, 'P3': 4, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0, 'P5': 0, 'P2': 0}, 'done_s': 5}), ('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 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: 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}), ('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 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}), ('control 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}), ('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 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 32', {'need': [['P2', 'N']], 'current': {'P1': 'N', 'P2': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'R'}, 'locked': ['P5', 'P6'], 'max_parallel': 2, 'throw_s': {'P1': 3, 'P2': 6, 'P3': 6}, '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 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}), ('sampled regression 27', {'need': [['P4', 'R'], ['P2', 'R'], ['P6', 'R']], 'current': {'P1': 'R', 'P2': 'N', 'P3': 'N', 'P4': 'N', 'P5': 'N', 'P6': 'N'}, 'locked': ['P3'], 'max_parallel': 1, 'throw_s': {'P2': 3, 'P3': 4, 'P4': 3, 'P5': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 0, 'P2': 3, 'P6': 6}, 'done_s': 11}), ('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: 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: 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}), ('sampled regression 65', {'need': [['P6', 'N']], 'current': {'P3': 'N', 'P4': 'N', 'P5': 'R', 'P6': 'R'}, 'locked': [], 'max_parallel': 3, 'throw_s': {'P2': 6, 'P3': 4, 'P4': 3, 'P6': 3}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P6': 0}, 'done_s': 3}), ('control 39', {'need': [['P4', 'N'], ['P3', 'R']], 'current': {'P1': 'R', 'P2': 'R', 'P3': 'R', 'P4': 'R', 'P5': 'R', 'P6': 'R'}, 'locked': ['P2'], 'max_parallel': 2, 'throw_s': {'P2': 6, 'P6': 4}, 'default_throw_s': 5}, {'result': 'set', 'starts': {'P4': 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}), ('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:
Route setting time ignores the individual throw time of slow or fast points.

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