prompt:
Bin powers are wildly high for bins whose states have the same sign.

Input [N, k, samples]; samples must have length N ("length-mismatch"). Goertzel recursion s = x + c s1 - s2 with c = 2 cos(2 pi k / N) from zero state; power = s1^2 + s2^2 - c s1 s2, rounded to 6 decimals (equals |X[k]|^2 of the DFT).

split: open-access


meaning: Fixture-count band, not measured model difficulty

deps: stdlib

prompt:
Both states always hold the newest value and the recursion becomes first order.

Input [N, k, samples]; samples must have length N ("length-mismatch"). Goertzel recursion s = x + c s1 - s2 with c = 2 cos(2 pi k / N) from zero state; power = s1^2 + s2^2 - c s1 s2, rounded to 6 decimals (equals |X[k]|^2 of the DFT).

split: open-access


prompt:
The resonator is tuned to the wrong frequency and DC input does not accumulate linearly.

Input [N, k, samples]; samples must have length N ("length-mismatch"). Goertzel recursion s = x + c s1 - s2 with c = 2 cos(2 pi k / N) from zero state; power = s1^2 + s2^2 - c s1 s2, rounded to 6 decimals (equals |X[k]|^2 of the DFT).

split: open-access


prompt:
Tones exactly on bin k leak and the reported power is too low.

Input [N, k, samples]; samples must have length N ("length-mismatch"). Goertzel recursion s = x + c s1 - s2 with c = 2 cos(2 pi k / N) from zero state; power = s1^2 + s2^2 - c s1 s2, rounded to 6 decimals (equals |X[k]|^2 of the DFT).

split: open-access


prompt:
The impulse response has a single echo instead of a decaying train.

Input [D, g, samples]: y[n] = x[n] + g y[n-D] using a D-slot ring buffer with zero initial state; "bad-delay" if D < 1, "unstable" if |g| >= 1. Return exact fraction strings.

split: open-access


prompt:
Echoes arrive after one sample regardless of D.

Input [D, g, samples]: y[n] = x[n] + g y[n-D] using a D-slot ring buffer with zero initial state; "bad-delay" if D < 1, "unstable" if |g| >= 1. Return exact fraction strings.

split: open-access


prompt:
g = 1 is accepted, giving a non-decaying (marginally stable) resonator instead of "unstable".

Input [D, g, samples]: y[n] = x[n] + g y[n-D] using a D-slot ring buffer with zero initial state; "bad-delay" if D < 1, "unstable" if |g| >= 1. Return exact fraction strings.

split: open-access


prompt:
A constant input produces a decaying spike equal to the offset at start-up.

Input [R, samples]: y[n] = x[n] - x[n-1] + R y[n-1] with 0 <= R < 1 ("bad-pole"), warm-started so x[-1] = x[0] and y[-1] = 0 (no start-up step). Return exact fraction strings.

split: open-access


prompt:
The pole sits at -R, producing an alternating tail instead of a slow decay.

Input [R, samples]: y[n] = x[n] - x[n-1] + R y[n-1] with 0 <= R < 1 ("bad-pole"), warm-started so x[-1] = x[0] and y[-1] = 0 (no start-up step). Return exact fraction strings.

split: open-access


prompt:
The feedback path is dead and the blocker becomes a plain first difference.

Input [R, samples]: y[n] = x[n] - x[n-1] + R y[n-1] with 0 <= R < 1 ("bad-pole"), warm-started so x[-1] = x[0] and y[-1] = 0 (no start-up step). Return exact fraction strings.

split: open-access


prompt:
A response that dips below eps, rebounds and dips again is truncated while still ringing.

Input [b, a, eps, maxlen, hold]; normalize by a0 ("bad-a0"), compute the impulse response exactly and stop after hold consecutive samples with |h| < eps, counted only once n >= len(b) - 1 (any non-quiet sample resets the count), or at maxlen. Return the kept samples as fraction strings.

split: open-access


prompt:
An alternating response is cut at its first large negative sample.

Input [b, a, eps, maxlen, hold]; normalize by a0 ("bad-a0"), compute the impulse response exactly and stop after hold consecutive samples with |h| < eps, counted only once n >= len(b) - 1 (any non-quiet sample resets the count), or at maxlen. Return the kept samples as fraction strings.

split: open-access


prompt:
A numerator with internal zeros such as [1, 0, 0, 1] is truncated before its last tap takes effect.

Input [b, a, eps, maxlen, hold]; normalize by a0 ("bad-a0"), compute the impulse response exactly and stop after hold consecutive samples with |h| < eps, counted only once n >= len(b) - 1 (any non-quiet sample resets the count), or at maxlen. Return the kept samples as fraction strings.

split: open-access


prompt:
With a0 = 2 the numerator is never scaled and the response is twice too large.

Input [b, a, eps, maxlen, hold]; normalize by a0 ("bad-a0"), compute the impulse response exactly and stop after hold consecutive samples with |h| < eps, counted only once n >= len(b) - 1 (any non-quiet sample resets the count), or at maxlen. Return the kept samples as fraction strings.

split: open-access


prompt:
Many small products each truncate to zero or -1, biasing the output.

Input [coeffs, samples] as Q15 integers. Each output accumulates the full-precision products c_k x[n-k] (zero history) in a wide accumulator, then rounds once (add 2**14, arithmetic shift 15) and saturates to int16. Return {"y": outputs, "saturations": number of clipped outputs}.

split: open-access


prompt:
A negative full-scale burst reports zero saturations.

Input [coeffs, samples] as Q15 integers. Each output accumulates the full-precision products c_k x[n-k] (zero history) in a wide accumulator, then rounds once (add 2**14, arithmetic shift 15) and saturates to int16. Return {"y": outputs, "saturations": number of clipped outputs}.

split: open-access


prompt:
The impulse response comes out reversed for asymmetric taps.

Input [coeffs, samples] as Q15 integers. Each output accumulates the full-precision products c_k x[n-k] (zero history) in a wide accumulator, then rounds once (add 2**14, arithmetic shift 15) and saturates to int16. Return {"y": outputs, "saturations": number of clipped outputs}.

split: open-access


prompt:
A 50 Hz notch at 1 kHz sampling attenuates 25 Hz instead.

Input [f0, fs, r]: second-order notch with zeros on the unit circle at +-w0 (w0 = 2 pi f0 / fs) and poles at radius r: b = [1, -2 cos w0, 1], a = [1, -2 r cos w0, r^2]; b is scaled for unity DC gain (sum(a)/sum(b)). Coefficients rounded to 9 decimals; "bad-frequency" unless 0 < f0 < fs/2, "bad-radius" unless 0 <= r < 1.

split: open-access


prompt:
The poles do not sit at radius r; the notch is far wider than specified.

Input [f0, fs, r]: second-order notch with zeros on the unit circle at +-w0 (w0 = 2 pi f0 / fs) and poles at radius r: b = [1, -2 cos w0, 1], a = [1, -2 r cos w0, r^2]; b is scaled for unity DC gain (sum(a)/sum(b)). Coefficients rounded to 9 decimals; "bad-frequency" unless 0 < f0 < fs/2, "bad-radius" unless 0 <= r < 1.

split: open-access


prompt:
The notch appears at fs/2 - f0.

Input [f0, fs, r]: second-order notch with zeros on the unit circle at +-w0 (w0 = 2 pi f0 / fs) and poles at radius r: b = [1, -2 cos w0, 1], a = [1, -2 r cos w0, r^2]; b is scaled for unity DC gain (sum(a)/sum(b)). Coefficients rounded to 9 decimals; "bad-frequency" unless 0 < f0 < fs/2, "bad-radius" unless 0 <= r < 1.

split: open-access


prompt:
The passband gain is squared away from unity instead of corrected.

Input [f0, fs, r]: second-order notch with zeros on the unit circle at +-w0 (w0 = 2 pi f0 / fs) and poles at radius r: b = [1, -2 cos w0, 1], a = [1, -2 r cos w0, r^2]; b is scaled for unity DC gain (sum(a)/sum(b)). Coefficients rounded to 9 decimals; "bad-frequency" unless 0 < f0 < fs/2, "bad-radius" unless 0 <= r < 1.

split: open-access


prompt:
The magnitude response is no longer flat; the section boosts low frequencies.

Input [a, samples]: y[n] = a x[n] + x[n-1] - a y[n-1] with zero state, "unstable" if |a| >= 1. Return exact fraction strings.

split: open-access


prompt:
The section is not allpass; its DC gain differs from 1.

Input [a, samples]: y[n] = a x[n] + x[n-1] - a y[n-1] with zero state, "unstable" if |a| >= 1. Return exact fraction strings.

split: open-access


prompt:
The impulse response differs from the allpass kernel after the first sample.

Input [a, samples]: y[n] = a x[n] + x[n-1] - a y[n-1] with zero state, "unstable" if |a| >= 1. Return exact fraction strings.

split: open-access


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

N = 1
observations = []
def solve(preset, scans):
    acc = 0
    prev = False
    out = []
    for rung_in, dt in scans:
        rung_in = bool(rung_in)
        if rung_in:
            acc = min(preset, acc + dt)
        elif not rung_in:
            acc = 0
        dn = rung_in and acc >= preset
        tt = rung_in and not dn
        prev = rung_in
        out.append([dn, tt, acc])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [30, [[True, 40], [False, 75], [True, 60], [False, 25], [False, 10], [True, 60], [True, 25], [True, 40]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30]]],
  ['regression: scenario 2',
   [30, [[False, 25], [True, 50], [True, 0], [True, 0], [True, 25], [True, 75], [True, 75]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30],
    [True, False, 30]]],
  ['regression: scenario 3',
   [120, [[True, 25], [True, 20], [False, 75], [True, 75], [True, 0], [False, 10], [True, 25]]],
   [[False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0]]],
  ['control: scenario 4',
   [0,
    [[True, 10],
     [False, 25],
     [True, 25],
     [True, 20],
     [True, 40],
     [True, 20],
     [True, 75],
     [True, 0],
     [True, 10]]],
   [[True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]]],
 [['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['control: scenario 1',
   [0,
    [[True, 40],
     [True, 10],
     [True, 10],
     [False, 10],
     [True, 20],
     [True, 25],
     [True, 20],
     [False, 25],
     [True, 20]]],
   [[True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0]]],
  ['regression: scenario 2',
   [150,
    [[True, 60],
     [True, 10],
     [False, 20],
     [False, 40],
     [True, 50],
     [True, 25],
     [False, 25],
     [False, 75],
     [True, 25],
     [False, 0],
     [True, 60],
     [False, 10]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 3',
   [50,
    [[False, 50],
     [True, 75],
     [True, 75],
     [True, 20],
     [True, 75],
     [True, 0],
     [False, 60],
     [True, 25],
     [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 4',
   [120,
    [[True, 75],
     [False, 60],
     [True, 20],
     [True, 25],
     [False, 40],
     [False, 40],
     [True, 50],
     [True, 60],
     [True, 75],
     [True, 40],
     [True, 0]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 60],
    [True, False, 120],
    [True, False, 120],
    [True, False, 120]]]],
 [['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [50,
    [[True, 75],
     [True, 40],
     [True, 60],
     [True, 0],
     [True, 25],
     [False, 50],
     [False, 75],
     [True, 60],
     [True, 20],
     [True, 60],
     [False, 60],
     [True, 75]]],
   [[False, True, 0],
    [False, True, 40],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: scenario 2',
   [120, [[False, 0], [False, 75], [True, 75], [True, 0], [True, 0], [False, 75], [True, 60], [True, 40]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40]]],
  ['regression: scenario 3',
   [50,
    [[True, 40],
     [False, 0],
     [True, 60],
     [True, 0],
     [True, 40],
     [True, 0],
     [True, 0],
     [False, 0],
     [False, 50],
     [False, 60],
     [False, 10],
     [True, 60]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 40],
    [False, True, 40],
    [False, True, 40],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0]]],
  ['regression: scenario 4',
   [100, [[False, 60], [False, 20], [True, 75], [False, 25], [True, 60], [False, 25], [True, 40]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0]]]],
 [['regression: scenario 2',
   [100, [[False, 50], [True, 50], [True, 20], [False, 50], [True, 40], [True, 10], [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 10],
    [False, False, 0]]],
  ['regression: scenario 3',
   [120,
    [[True, 60],
     [True, 10],
     [False, 10],
     [True, 50],
     [True, 20],
     [True, 25],
     [True, 25],
     [False, 75],
     [True, 40],
     [True, 50],
     [True, 75],
     [True, 0]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 45],
    [False, True, 70],
    [False, False, 0],
    [False, True, 0],
    [False, True, 50],
    [True, False, 120],
    [True, False, 120]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['control: scenario 1',
   [0,
    [[True, 10],
     [True, 0],
     [False, 50],
     [True, 40],
     [False, 20],
     [False, 25],
     [True, 50],
     [True, 60],
     [True, 40]]],
   [[True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]],
  ['control: scenario 4',
   [0, [[True, 25], [False, 75], [True, 20], [False, 25], [True, 20], [False, 25], [True, 40]]],
   [[True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0]]]],
 [['regression: scenario 2',
   [150, [[True, 50], [False, 40], [True, 20], [True, 20], [True, 10], [True, 40], [False, 50]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 30],
    [False, True, 70],
    [False, False, 0]]],
  ['regression: scenario 3',
   [200,
    [[False, 20],
     [False, 50],
     [True, 75],
     [False, 60],
     [False, 50],
     [True, 0],
     [True, 25],
     [True, 20],
     [True, 40],
     [True, 25],
     [True, 25],
     [True, 60]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, True, 45],
    [False, True, 85],
    [False, True, 110],
    [False, True, 135],
    [False, True, 195]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [120,
    [[True, 0],
     [True, 50],
     [True, 50],
     [True, 75],
     [True, 75],
     [False, 40],
     [True, 25],
     [False, 0],
     [False, 10],
     [True, 25],
     [False, 0]]],
   [[False, True, 0],
    [False, True, 50],
    [False, True, 100],
    [True, False, 120],
    [True, False, 120],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 4',
   [100,
    [[False, 60],
     [False, 0],
     [True, 50],
     [True, 20],
     [True, 60],
     [True, 20],
     [True, 50],
     [True, 0],
     [True, 20],
     [True, 0],
     [True, 20],
     [True, 25]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 80],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100]]]]]
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(preset, scans):
    acc = 0
    prev = False
    out = []
    for rung_in, dt in scans:
        rung_in = bool(rung_in)
        if rung_in:
            acc = min(preset, acc + (dt if prev else dt // 2))
        elif not rung_in:
            acc = 0
        dn = rung_in and acc >= preset
        tt = rung_in and not dn
        prev = rung_in
        out.append([dn, tt, acc])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [30, [[True, 40], [False, 75], [True, 60], [False, 25], [False, 10], [True, 60], [True, 25], [True, 40]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30]]],
  ['regression: scenario 2',
   [30, [[False, 25], [True, 50], [True, 0], [True, 0], [True, 25], [True, 75], [True, 75]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30],
    [True, False, 30]]],
  ['regression: scenario 3',
   [120, [[True, 25], [True, 20], [False, 75], [True, 75], [True, 0], [False, 10], [True, 25]]],
   [[False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0]]],
  ['control: scenario 4',
   [0,
    [[True, 10],
     [False, 25],
     [True, 25],
     [True, 20],
     [True, 40],
     [True, 20],
     [True, 75],
     [True, 0],
     [True, 10]]],
   [[True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]]],
 [['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['control: scenario 1',
   [0,
    [[True, 40],
     [True, 10],
     [True, 10],
     [False, 10],
     [True, 20],
     [True, 25],
     [True, 20],
     [False, 25],
     [True, 20]]],
   [[True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0]]],
  ['regression: scenario 2',
   [150,
    [[True, 60],
     [True, 10],
     [False, 20],
     [False, 40],
     [True, 50],
     [True, 25],
     [False, 25],
     [False, 75],
     [True, 25],
     [False, 0],
     [True, 60],
     [False, 10]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 3',
   [50,
    [[False, 50],
     [True, 75],
     [True, 75],
     [True, 20],
     [True, 75],
     [True, 0],
     [False, 60],
     [True, 25],
     [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 4',
   [120,
    [[True, 75],
     [False, 60],
     [True, 20],
     [True, 25],
     [False, 40],
     [False, 40],
     [True, 50],
     [True, 60],
     [True, 75],
     [True, 40],
     [True, 0]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 60],
    [True, False, 120],
    [True, False, 120],
    [True, False, 120]]]],
 [['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [50,
    [[True, 75],
     [True, 40],
     [True, 60],
     [True, 0],
     [True, 25],
     [False, 50],
     [False, 75],
     [True, 60],
     [True, 20],
     [True, 60],
     [False, 60],
     [True, 75]]],
   [[False, True, 0],
    [False, True, 40],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: scenario 2',
   [120, [[False, 0], [False, 75], [True, 75], [True, 0], [True, 0], [False, 75], [True, 60], [True, 40]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40]]],
  ['regression: scenario 3',
   [50,
    [[True, 40],
     [False, 0],
     [True, 60],
     [True, 0],
     [True, 40],
     [True, 0],
     [True, 0],
     [False, 0],
     [False, 50],
     [False, 60],
     [False, 10],
     [True, 60]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 40],
    [False, True, 40],
    [False, True, 40],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0]]],
  ['regression: scenario 4',
   [100, [[False, 60], [False, 20], [True, 75], [False, 25], [True, 60], [False, 25], [True, 40]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0]]]],
 [['regression: scenario 2',
   [100, [[False, 50], [True, 50], [True, 20], [False, 50], [True, 40], [True, 10], [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 10],
    [False, False, 0]]],
  ['regression: scenario 3',
   [120,
    [[True, 60],
     [True, 10],
     [False, 10],
     [True, 50],
     [True, 20],
     [True, 25],
     [True, 25],
     [False, 75],
     [True, 40],
     [True, 50],
     [True, 75],
     [True, 0]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 45],
    [False, True, 70],
    [False, False, 0],
    [False, True, 0],
    [False, True, 50],
    [True, False, 120],
    [True, False, 120]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['control: scenario 1',
   [0,
    [[True, 10],
     [True, 0],
     [False, 50],
     [True, 40],
     [False, 20],
     [False, 25],
     [True, 50],
     [True, 60],
     [True, 40]]],
   [[True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]],
  ['control: scenario 4',
   [0, [[True, 25], [False, 75], [True, 20], [False, 25], [True, 20], [False, 25], [True, 40]]],
   [[True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0]]]],
 [['regression: scenario 2',
   [150, [[True, 50], [False, 40], [True, 20], [True, 20], [True, 10], [True, 40], [False, 50]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 30],
    [False, True, 70],
    [False, False, 0]]],
  ['regression: scenario 3',
   [200,
    [[False, 20],
     [False, 50],
     [True, 75],
     [False, 60],
     [False, 50],
     [True, 0],
     [True, 25],
     [True, 20],
     [True, 40],
     [True, 25],
     [True, 25],
     [True, 60]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, True, 45],
    [False, True, 85],
    [False, True, 110],
    [False, True, 135],
    [False, True, 195]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [120,
    [[True, 0],
     [True, 50],
     [True, 50],
     [True, 75],
     [True, 75],
     [False, 40],
     [True, 25],
     [False, 0],
     [False, 10],
     [True, 25],
     [False, 0]]],
   [[False, True, 0],
    [False, True, 50],
    [False, True, 100],
    [True, False, 120],
    [True, False, 120],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 4',
   [100,
    [[False, 60],
     [False, 0],
     [True, 50],
     [True, 20],
     [True, 60],
     [True, 20],
     [True, 50],
     [True, 0],
     [True, 20],
     [True, 0],
     [True, 20],
     [True, 25]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 80],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100]]]]]
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 on-delay finishes one scan early because the scan that energized the rung already contributes elapsed time.

On-delay timer (TON) evaluated once per scan. scans is a list of [rung_in, elapsed_ms since the previous scan]. The accumulator starts on the false-to-true scan without crediting that scan's elapsed time, then adds each later true scan's elapsed time, clamped at preset. A false rung resets the accumulator. DN is rung_in and acc >= preset; TT is rung_in and not DN. Return [DN, TT, ACC] per scan.

split: open-access


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

N = 1
observations = []
def solve(preset, scans):
    acc = 0
    prev = False
    out = []
    for rung_in, dt in scans:
        rung_in = bool(rung_in)
        if rung_in and prev:
            acc = acc + dt
        elif not rung_in:
            acc = 0
        dn = rung_in and acc >= preset
        tt = rung_in and not dn
        prev = rung_in
        out.append([dn, tt, acc])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [30, [[True, 40], [False, 75], [True, 60], [False, 25], [False, 10], [True, 60], [True, 25], [True, 40]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30]]],
  ['regression: scenario 2',
   [30, [[False, 25], [True, 50], [True, 0], [True, 0], [True, 25], [True, 75], [True, 75]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30],
    [True, False, 30]]],
  ['control: scenario 3',
   [120, [[True, 25], [True, 20], [False, 75], [True, 75], [True, 0], [False, 10], [True, 25]]],
   [[False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0]]],
  ['regression: scenario 4',
   [0,
    [[True, 10],
     [False, 25],
     [True, 25],
     [True, 20],
     [True, 40],
     [True, 20],
     [True, 75],
     [True, 0],
     [True, 10]]],
   [[True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]]],
 [['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: scenario 1',
   [0,
    [[True, 40],
     [True, 10],
     [True, 10],
     [False, 10],
     [True, 20],
     [True, 25],
     [True, 20],
     [False, 25],
     [True, 20]]],
   [[True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0]]],
  ['control: scenario 2',
   [150,
    [[True, 60],
     [True, 10],
     [False, 20],
     [False, 40],
     [True, 50],
     [True, 25],
     [False, 25],
     [False, 75],
     [True, 25],
     [False, 0],
     [True, 60],
     [False, 10]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 3',
   [50,
    [[False, 50],
     [True, 75],
     [True, 75],
     [True, 20],
     [True, 75],
     [True, 0],
     [False, 60],
     [True, 25],
     [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 4',
   [120,
    [[True, 75],
     [False, 60],
     [True, 20],
     [True, 25],
     [False, 40],
     [False, 40],
     [True, 50],
     [True, 60],
     [True, 75],
     [True, 40],
     [True, 0]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 60],
    [True, False, 120],
    [True, False, 120],
    [True, False, 120]]]],
 [['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [50,
    [[True, 75],
     [True, 40],
     [True, 60],
     [True, 0],
     [True, 25],
     [False, 50],
     [False, 75],
     [True, 60],
     [True, 20],
     [True, 60],
     [False, 60],
     [True, 75]]],
   [[False, True, 0],
    [False, True, 40],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['control: scenario 2',
   [120, [[False, 0], [False, 75], [True, 75], [True, 0], [True, 0], [False, 75], [True, 60], [True, 40]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40]]],
  ['control: scenario 3',
   [50,
    [[True, 40],
     [False, 0],
     [True, 60],
     [True, 0],
     [True, 40],
     [True, 0],
     [True, 0],
     [False, 0],
     [False, 50],
     [False, 60],
     [False, 10],
     [True, 60]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 40],
    [False, True, 40],
    [False, True, 40],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0]]],
  ['control: scenario 4',
   [100, [[False, 60], [False, 20], [True, 75], [False, 25], [True, 60], [False, 25], [True, 40]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0]]]],
 [['regression: scenario 1',
   [0,
    [[True, 10],
     [True, 0],
     [False, 50],
     [True, 40],
     [False, 20],
     [False, 25],
     [True, 50],
     [True, 60],
     [True, 40]]],
   [[True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]],
  ['regression: scenario 3',
   [120,
    [[True, 60],
     [True, 10],
     [False, 10],
     [True, 50],
     [True, 20],
     [True, 25],
     [True, 25],
     [False, 75],
     [True, 40],
     [True, 50],
     [True, 75],
     [True, 0]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 45],
    [False, True, 70],
    [False, False, 0],
    [False, True, 0],
    [False, True, 50],
    [True, False, 120],
    [True, False, 120]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['control: scenario 2',
   [100, [[False, 50], [True, 50], [True, 20], [False, 50], [True, 40], [True, 10], [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 10],
    [False, False, 0]]],
  ['control: scenario 4',
   [0, [[True, 25], [False, 75], [True, 20], [False, 25], [True, 20], [False, 25], [True, 40]]],
   [[True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0]]]],
 [['regression: scenario 4',
   [100,
    [[False, 60],
     [False, 0],
     [True, 50],
     [True, 20],
     [True, 60],
     [True, 20],
     [True, 50],
     [True, 0],
     [True, 20],
     [True, 0],
     [True, 20],
     [True, 25]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 80],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100]]],
  ['regression: scenario 5',
   [100,
    [[True, 20],
     [True, 40],
     [True, 20],
     [True, 75],
     [True, 50],
     [True, 75],
     [True, 0],
     [True, 25],
     [False, 50],
     [False, 0],
     [False, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, True, 60],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [120,
    [[True, 0],
     [True, 50],
     [True, 50],
     [True, 75],
     [True, 75],
     [False, 40],
     [True, 25],
     [False, 0],
     [False, 10],
     [True, 25],
     [False, 0]]],
   [[False, True, 0],
    [False, True, 50],
    [False, True, 100],
    [True, False, 120],
    [True, False, 120],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['control: scenario 2',
   [150, [[True, 50], [False, 40], [True, 20], [True, 20], [True, 10], [True, 40], [False, 50]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 30],
    [False, True, 70],
    [False, False, 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(preset, scans):
    acc = 0
    prev = False
    out = []
    for rung_in, dt in scans:
        rung_in = bool(rung_in)
        if rung_in and prev:
            acc = min(preset, acc) + dt
        elif not rung_in:
            acc = 0
        dn = rung_in and acc >= preset
        tt = rung_in and not dn
        prev = rung_in
        out.append([dn, tt, acc])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [30, [[True, 40], [False, 75], [True, 60], [False, 25], [False, 10], [True, 60], [True, 25], [True, 40]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30]]],
  ['regression: scenario 2',
   [30, [[False, 25], [True, 50], [True, 0], [True, 0], [True, 25], [True, 75], [True, 75]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30],
    [True, False, 30]]],
  ['control: scenario 3',
   [120, [[True, 25], [True, 20], [False, 75], [True, 75], [True, 0], [False, 10], [True, 25]]],
   [[False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0]]],
  ['regression: scenario 4',
   [0,
    [[True, 10],
     [False, 25],
     [True, 25],
     [True, 20],
     [True, 40],
     [True, 20],
     [True, 75],
     [True, 0],
     [True, 10]]],
   [[True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]]],
 [['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: scenario 1',
   [0,
    [[True, 40],
     [True, 10],
     [True, 10],
     [False, 10],
     [True, 20],
     [True, 25],
     [True, 20],
     [False, 25],
     [True, 20]]],
   [[True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0]]],
  ['control: scenario 2',
   [150,
    [[True, 60],
     [True, 10],
     [False, 20],
     [False, 40],
     [True, 50],
     [True, 25],
     [False, 25],
     [False, 75],
     [True, 25],
     [False, 0],
     [True, 60],
     [False, 10]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 3',
   [50,
    [[False, 50],
     [True, 75],
     [True, 75],
     [True, 20],
     [True, 75],
     [True, 0],
     [False, 60],
     [True, 25],
     [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 4',
   [120,
    [[True, 75],
     [False, 60],
     [True, 20],
     [True, 25],
     [False, 40],
     [False, 40],
     [True, 50],
     [True, 60],
     [True, 75],
     [True, 40],
     [True, 0]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 60],
    [True, False, 120],
    [True, False, 120],
    [True, False, 120]]]],
 [['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [50,
    [[True, 75],
     [True, 40],
     [True, 60],
     [True, 0],
     [True, 25],
     [False, 50],
     [False, 75],
     [True, 60],
     [True, 20],
     [True, 60],
     [False, 60],
     [True, 75]]],
   [[False, True, 0],
    [False, True, 40],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['control: scenario 2',
   [120, [[False, 0], [False, 75], [True, 75], [True, 0], [True, 0], [False, 75], [True, 60], [True, 40]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40]]],
  ['control: scenario 3',
   [50,
    [[True, 40],
     [False, 0],
     [True, 60],
     [True, 0],
     [True, 40],
     [True, 0],
     [True, 0],
     [False, 0],
     [False, 50],
     [False, 60],
     [False, 10],
     [True, 60]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 40],
    [False, True, 40],
    [False, True, 40],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0]]],
  ['control: scenario 4',
   [100, [[False, 60], [False, 20], [True, 75], [False, 25], [True, 60], [False, 25], [True, 40]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0]]]],
 [['regression: scenario 1',
   [0,
    [[True, 10],
     [True, 0],
     [False, 50],
     [True, 40],
     [False, 20],
     [False, 25],
     [True, 50],
     [True, 60],
     [True, 40]]],
   [[True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]],
  ['regression: scenario 3',
   [120,
    [[True, 60],
     [True, 10],
     [False, 10],
     [True, 50],
     [True, 20],
     [True, 25],
     [True, 25],
     [False, 75],
     [True, 40],
     [True, 50],
     [True, 75],
     [True, 0]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 45],
    [False, True, 70],
    [False, False, 0],
    [False, True, 0],
    [False, True, 50],
    [True, False, 120],
    [True, False, 120]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['control: scenario 2',
   [100, [[False, 50], [True, 50], [True, 20], [False, 50], [True, 40], [True, 10], [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 10],
    [False, False, 0]]],
  ['control: scenario 4',
   [0, [[True, 25], [False, 75], [True, 20], [False, 25], [True, 20], [False, 25], [True, 40]]],
   [[True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0]]]],
 [['regression: scenario 4',
   [100,
    [[False, 60],
     [False, 0],
     [True, 50],
     [True, 20],
     [True, 60],
     [True, 20],
     [True, 50],
     [True, 0],
     [True, 20],
     [True, 0],
     [True, 20],
     [True, 25]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 80],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100]]],
  ['regression: scenario 5',
   [100,
    [[True, 20],
     [True, 40],
     [True, 20],
     [True, 75],
     [True, 50],
     [True, 75],
     [True, 0],
     [True, 25],
     [False, 50],
     [False, 0],
     [False, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, True, 60],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0]]],
  ['regression: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [120,
    [[True, 0],
     [True, 50],
     [True, 50],
     [True, 75],
     [True, 75],
     [False, 40],
     [True, 25],
     [False, 0],
     [False, 10],
     [True, 25],
     [False, 0]]],
   [[False, True, 0],
    [False, True, 50],
    [False, True, 100],
    [True, False, 120],
    [True, False, 120],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['control: scenario 2',
   [150, [[True, 50], [False, 40], [True, 20], [True, 20], [True, 10], [True, 40], [False, 50]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 30],
    [False, True, 70],
    [False, False, 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:
After the delay completes the ACC value keeps growing on every true scan instead of holding at PRE.

On-delay timer (TON) evaluated once per scan. scans is a list of [rung_in, elapsed_ms since the previous scan]. The accumulator starts on the false-to-true scan without crediting that scan's elapsed time, then adds each later true scan's elapsed time, clamped at preset. A false rung resets the accumulator. DN is rung_in and acc >= preset; TT is rung_in and not DN. Return [DN, TT, ACC] per scan.

split: open-access


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

N = 1
observations = []
def solve(preset, scans):
    acc = 0
    prev = False
    out = []
    for rung_in, dt in scans:
        rung_in = bool(rung_in)
        if rung_in and prev:
            acc = min(preset, acc + dt)
        elif not rung_in:
            pass
        dn = rung_in and acc >= preset
        tt = rung_in and not dn
        prev = rung_in
        out.append([dn, tt, acc])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: scenario 3',
   [120, [[True, 25], [True, 20], [False, 75], [True, 75], [True, 0], [False, 10], [True, 25]]],
   [[False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0]]],
  ['control: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['control: scenario 1',
   [30, [[True, 40], [False, 75], [True, 60], [False, 25], [False, 10], [True, 60], [True, 25], [True, 40]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30]]],
  ['control: scenario 2',
   [30, [[False, 25], [True, 50], [True, 0], [True, 0], [True, 25], [True, 75], [True, 75]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30],
    [True, False, 30]]],
  ['control: scenario 4',
   [0,
    [[True, 10],
     [False, 25],
     [True, 25],
     [True, 20],
     [True, 40],
     [True, 20],
     [True, 75],
     [True, 0],
     [True, 10]]],
   [[True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]]],
 [['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 2',
   [150,
    [[True, 60],
     [True, 10],
     [False, 20],
     [False, 40],
     [True, 50],
     [True, 25],
     [False, 25],
     [False, 75],
     [True, 25],
     [False, 0],
     [True, 60],
     [False, 10]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['control: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['control: scenario 1',
   [0,
    [[True, 40],
     [True, 10],
     [True, 10],
     [False, 10],
     [True, 20],
     [True, 25],
     [True, 20],
     [False, 25],
     [True, 20]]],
   [[True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0]]],
  ['regression: scenario 3',
   [50,
    [[False, 50],
     [True, 75],
     [True, 75],
     [True, 20],
     [True, 75],
     [True, 0],
     [False, 60],
     [True, 25],
     [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 4',
   [120,
    [[True, 75],
     [False, 60],
     [True, 20],
     [True, 25],
     [False, 40],
     [False, 40],
     [True, 50],
     [True, 60],
     [True, 75],
     [True, 40],
     [True, 0]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 60],
    [True, False, 120],
    [True, False, 120],
    [True, False, 120]]]],
 [['regression: scenario 1',
   [50,
    [[True, 75],
     [True, 40],
     [True, 60],
     [True, 0],
     [True, 25],
     [False, 50],
     [False, 75],
     [True, 60],
     [True, 20],
     [True, 60],
     [False, 60],
     [True, 75]]],
   [[False, True, 0],
    [False, True, 40],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0]]],
  ['regression: scenario 6',
   [30,
    [[True, 60],
     [True, 25],
     [False, 40],
     [True, 0],
     [True, 25],
     [True, 60],
     [False, 60],
     [True, 75],
     [True, 50],
     [False, 60],
     [True, 25],
     [True, 20],
     [True, 60]]],
   [[False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30],
    [False, False, 0],
    [False, True, 0],
    [True, False, 30],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [True, False, 30]]],
  ['control: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['control: scenario 2',
   [120, [[False, 0], [False, 75], [True, 75], [True, 0], [True, 0], [False, 75], [True, 60], [True, 40]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40]]],
  ['regression: scenario 3',
   [50,
    [[True, 40],
     [False, 0],
     [True, 60],
     [True, 0],
     [True, 40],
     [True, 0],
     [True, 0],
     [False, 0],
     [False, 50],
     [False, 60],
     [False, 10],
     [True, 60]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 40],
    [False, True, 40],
    [False, True, 40],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0]]]],
 [['regression: scenario 3',
   [120,
    [[True, 60],
     [True, 10],
     [False, 10],
     [True, 50],
     [True, 20],
     [True, 25],
     [True, 25],
     [False, 75],
     [True, 40],
     [True, 50],
     [True, 75],
     [True, 0]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 45],
    [False, True, 70],
    [False, False, 0],
    [False, True, 0],
    [False, True, 50],
    [True, False, 120],
    [True, False, 120]]],
  ['regression: scenario 7',
   [200, [[True, 60], [True, 0], [False, 20], [True, 20], [True, 10], [True, 60], [False, 10]]],
   [[False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 10],
    [False, True, 70],
    [False, False, 0]]],
  ['control: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['control: scenario 1',
   [0,
    [[True, 10],
     [True, 0],
     [False, 50],
     [True, 40],
     [False, 20],
     [False, 25],
     [True, 50],
     [True, 60],
     [True, 40]]],
   [[True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]],
  ['regression: scenario 2',
   [100, [[False, 50], [True, 50], [True, 20], [False, 50], [True, 40], [True, 10], [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 10],
    [False, False, 0]]]],
 [['regression: scenario 5',
   [100,
    [[True, 20],
     [True, 40],
     [True, 20],
     [True, 75],
     [True, 50],
     [True, 75],
     [True, 0],
     [True, 25],
     [False, 50],
     [False, 0],
     [False, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, True, 60],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0]]],
  ['regression: scenario 12',
   [100,
    [[True, 40],
     [True, 20],
     [False, 10],
     [False, 0],
     [True, 75],
     [True, 25],
     [True, 50],
     [True, 50],
     [True, 40],
     [False, 10],
     [True, 0],
     [True, 75],
     [False, 25]]],
   [[False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, True, 75],
    [True, False, 100],
    [True, False, 100],
    [False, False, 0],
    [False, True, 0],
    [False, True, 75],
    [False, False, 0]]],
  ['control: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [120,
    [[True, 0],
     [True, 50],
     [True, 50],
     [True, 75],
     [True, 75],
     [False, 40],
     [True, 25],
     [False, 0],
     [False, 10],
     [True, 25],
     [False, 0]]],
   [[False, True, 0],
    [False, True, 50],
    [False, True, 100],
    [True, False, 120],
    [True, False, 120],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 2',
   [150, [[True, 50], [False, 40], [True, 20], [True, 20], [True, 10], [True, 40], [False, 50]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 30],
    [False, True, 70],
    [False, False, 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(preset, scans):
    acc = 0
    prev = False
    out = []
    for rung_in, dt in scans:
        rung_in = bool(rung_in)
        if rung_in and prev:
            acc = min(preset, acc + dt)
        elif not rung_in and acc >= preset:
            acc = 0
        dn = rung_in and acc >= preset
        tt = rung_in and not dn
        prev = rung_in
        out.append([dn, tt, acc])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: scenario 3',
   [120, [[True, 25], [True, 20], [False, 75], [True, 75], [True, 0], [False, 10], [True, 25]]],
   [[False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0]]],
  ['control: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['control: scenario 1',
   [30, [[True, 40], [False, 75], [True, 60], [False, 25], [False, 10], [True, 60], [True, 25], [True, 40]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30]]],
  ['control: scenario 2',
   [30, [[False, 25], [True, 50], [True, 0], [True, 0], [True, 25], [True, 75], [True, 75]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30],
    [True, False, 30]]],
  ['control: scenario 4',
   [0,
    [[True, 10],
     [False, 25],
     [True, 25],
     [True, 20],
     [True, 40],
     [True, 20],
     [True, 75],
     [True, 0],
     [True, 10]]],
   [[True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]]],
 [['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 2',
   [150,
    [[True, 60],
     [True, 10],
     [False, 20],
     [False, 40],
     [True, 50],
     [True, 25],
     [False, 25],
     [False, 75],
     [True, 25],
     [False, 0],
     [True, 60],
     [False, 10]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['control: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['control: scenario 1',
   [0,
    [[True, 40],
     [True, 10],
     [True, 10],
     [False, 10],
     [True, 20],
     [True, 25],
     [True, 20],
     [False, 25],
     [True, 20]]],
   [[True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0]]],
  ['regression: scenario 3',
   [50,
    [[False, 50],
     [True, 75],
     [True, 75],
     [True, 20],
     [True, 75],
     [True, 0],
     [False, 60],
     [True, 25],
     [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 4',
   [120,
    [[True, 75],
     [False, 60],
     [True, 20],
     [True, 25],
     [False, 40],
     [False, 40],
     [True, 50],
     [True, 60],
     [True, 75],
     [True, 40],
     [True, 0]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 60],
    [True, False, 120],
    [True, False, 120],
    [True, False, 120]]]],
 [['regression: scenario 1',
   [50,
    [[True, 75],
     [True, 40],
     [True, 60],
     [True, 0],
     [True, 25],
     [False, 50],
     [False, 75],
     [True, 60],
     [True, 20],
     [True, 60],
     [False, 60],
     [True, 75]]],
   [[False, True, 0],
    [False, True, 40],
    [True, False, 50],
    [True, False, 50],
    [True, False, 50],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [True, False, 50],
    [False, False, 0],
    [False, True, 0]]],
  ['regression: scenario 6',
   [30,
    [[True, 60],
     [True, 25],
     [False, 40],
     [True, 0],
     [True, 25],
     [True, 60],
     [False, 60],
     [True, 75],
     [True, 50],
     [False, 60],
     [True, 25],
     [True, 20],
     [True, 60]]],
   [[False, True, 0],
    [False, True, 25],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [True, False, 30],
    [False, False, 0],
    [False, True, 0],
    [True, False, 30],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [True, False, 30]]],
  ['control: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['control: scenario 2',
   [120, [[False, 0], [False, 75], [True, 75], [True, 0], [True, 0], [False, 75], [True, 60], [True, 40]]],
   [[False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40]]],
  ['regression: scenario 3',
   [50,
    [[True, 40],
     [False, 0],
     [True, 60],
     [True, 0],
     [True, 40],
     [True, 0],
     [True, 0],
     [False, 0],
     [False, 50],
     [False, 60],
     [False, 10],
     [True, 60]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 0],
    [False, True, 40],
    [False, True, 40],
    [False, True, 40],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0]]]],
 [['regression: scenario 3',
   [120,
    [[True, 60],
     [True, 10],
     [False, 10],
     [True, 50],
     [True, 20],
     [True, 25],
     [True, 25],
     [False, 75],
     [True, 40],
     [True, 50],
     [True, 75],
     [True, 0]]],
   [[False, True, 0],
    [False, True, 10],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 45],
    [False, True, 70],
    [False, False, 0],
    [False, True, 0],
    [False, True, 50],
    [True, False, 120],
    [True, False, 120]]],
  ['regression: scenario 7',
   [200, [[True, 60], [True, 0], [False, 20], [True, 20], [True, 10], [True, 60], [False, 10]]],
   [[False, True, 0],
    [False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 10],
    [False, True, 70],
    [False, False, 0]]],
  ['control: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['control: scenario 1',
   [0,
    [[True, 10],
     [True, 0],
     [False, 50],
     [True, 40],
     [False, 20],
     [False, 25],
     [True, 50],
     [True, 60],
     [True, 40]]],
   [[True, False, 0],
    [True, False, 0],
    [False, False, 0],
    [True, False, 0],
    [False, False, 0],
    [False, False, 0],
    [True, False, 0],
    [True, False, 0],
    [True, False, 0]]],
  ['regression: scenario 2',
   [100, [[False, 50], [True, 50], [True, 20], [False, 50], [True, 40], [True, 10], [False, 10]]],
   [[False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, True, 0],
    [False, True, 10],
    [False, False, 0]]]],
 [['regression: scenario 5',
   [100,
    [[True, 20],
     [True, 40],
     [True, 20],
     [True, 75],
     [True, 50],
     [True, 75],
     [True, 0],
     [True, 25],
     [False, 50],
     [False, 0],
     [False, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, True, 60],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [True, False, 100],
    [False, False, 0],
    [False, False, 0],
    [False, False, 0]]],
  ['regression: scenario 12',
   [100,
    [[True, 40],
     [True, 20],
     [False, 10],
     [False, 0],
     [True, 75],
     [True, 25],
     [True, 50],
     [True, 50],
     [True, 40],
     [False, 10],
     [True, 0],
     [True, 75],
     [False, 25]]],
   [[False, True, 0],
    [False, True, 20],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 25],
    [False, True, 75],
    [True, False, 100],
    [True, False, 100],
    [False, False, 0],
    [False, True, 0],
    [False, True, 75],
    [False, False, 0]]],
  ['control: preset reached exactly',
   [100, [[True, 30], [True, 50], [True, 50], [True, 10]]],
   [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]]],
  ['control: zero preset',
   [0, [[False, 10], [True, 10], [False, 5], [True, 40]]],
   [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]]],
  ['regression: interrupted timing restarts',
   [60, [[True, 40], [True, 40], [False, 40], [True, 40], [True, 40], [True, 40]]],
   [[False, True, 0],
    [False, True, 40],
    [False, False, 0],
    [False, True, 0],
    [False, True, 40],
    [True, False, 60]]],
  ['regression: long hold after done',
   [50, [[True, 30], [True, 30], [True, 30], [True, 30], [False, 30]]],
   [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]]],
  ['regression: scenario 1',
   [120,
    [[True, 0],
     [True, 50],
     [True, 50],
     [True, 75],
     [True, 75],
     [False, 40],
     [True, 25],
     [False, 0],
     [False, 10],
     [True, 25],
     [False, 0]]],
   [[False, True, 0],
    [False, True, 50],
    [False, True, 100],
    [True, False, 120],
    [True, False, 120],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0],
    [False, False, 0],
    [False, True, 0],
    [False, False, 0]]],
  ['regression: scenario 2',
   [150, [[True, 50], [False, 40], [True, 20], [True, 20], [True, 10], [True, 40], [False, 50]]],
   [[False, True, 0],
    [False, False, 0],
    [False, True, 0],
    [False, True, 20],
    [False, True, 30],
    [False, True, 70],
    [False, False, 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 second energization completes too soon because time accumulated before an interruption is kept.

On-delay timer (TON) evaluated once per scan. scans is a list of [rung_in, elapsed_ms since the previous scan]. The accumulator starts on the false-to-true scan without crediting that scan's elapsed time, then adds each later true scan's elapsed time, clamped at preset. A false rung resets the accumulator. DN is rung_in and acc >= preset; TT is rung_in and not DN. Return [DN, TT, ACC] per scan.

split: open-access