FA-91851 / PLC ladder logic scan cycles / Open access
TON behaves retentively when its rung drops · case 01
A second energization completes too soon because time accumulated before an interruption is kept.
ROOT CAUSE
The false-rung branch leaves the accumulator untouched, turning TON into a retentive timer.
VERIFIED REPAIR
Reset the accumulator on every false-rung scan.
Unsuccessful approach: Resetting only a timer that had already finished still keeps partial time across an interruption.
Case contract
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.
Why this case matters
Ladder programs are executed as repeated scans; each defect here changes what a rung, timer, counter or data-table instruction reports on a particular scan, which is how commissioning and field faults are actually observed.
1 / The failure
Exit 1"""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)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: interrupted timing restarts | [[False, True, 0], [False, True, 40], [False, False, 40], [False, True, 40], [True, False, 60], [True, False, 60]] | [[False, True, 0], [False, True, 40], [False, False, 0], [False, True, 0], [False, True, 40], [True, False, 60]] | Failed |
| regression: scenario 3 | [[False, True, 0], [False, True, 20], [False, False, 20], [False, True, 20], [False, True, 20], [False, False, 20], [False, True, 20]] | [[False, True, 0], [False, True, 20], [False, False, 0], [False, True, 0], [False, True, 0], [False, False, 0], [False, True, 0]] | Failed |
| control: preset reached exactly | [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]] | [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]] | Passed |
| control: zero preset | [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]] | [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]] | Passed |
| regression: long hold after done | [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 50]] | [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]] | Failed |
| control: scenario 1 | [[False, True, 0], [False, False, 0], [False, True, 0], [False, False, 0], [False, False, 0], [False, True, 0], [False, True, 25], [True, False, 30]] | [[False, True, 0], [False, False, 0], [False, True, 0], [False, False, 0], [False, False, 0], [False, True, 0], [False, True, 25], [True, False, 30]] | Passed |
| control: scenario 2 | [[False, False, 0], [False, True, 0], [False, True, 0], [False, True, 0], [False, True, 25], [True, False, 30], [True, False, 30]] | [[False, False, 0], [False, True, 0], [False, True, 0], [False, True, 0], [False, True, 25], [True, False, 30], [True, False, 30]] | Passed |
| control: scenario 4 | [[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]] | [[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]] | Passed |
SHA-256 / 4e882686f4cb14668b9cc5d254a18f8a036ada9d332b087d108dab0788770a8a
2 / The unsuccessful fix
Exit 1"""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)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: interrupted timing restarts | [[False, True, 0], [False, True, 40], [False, False, 40], [False, True, 40], [True, False, 60], [True, False, 60]] | [[False, True, 0], [False, True, 40], [False, False, 0], [False, True, 0], [False, True, 40], [True, False, 60]] | Failed |
| regression: scenario 3 | [[False, True, 0], [False, True, 20], [False, False, 20], [False, True, 20], [False, True, 20], [False, False, 20], [False, True, 20]] | [[False, True, 0], [False, True, 20], [False, False, 0], [False, True, 0], [False, True, 0], [False, False, 0], [False, True, 0]] | Failed |
| control: preset reached exactly | [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]] | [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]] | Passed |
| control: zero preset | [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]] | [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]] | Passed |
| regression: long hold after done | [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]] | [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]] | Passed |
| control: scenario 1 | [[False, True, 0], [False, False, 0], [False, True, 0], [False, False, 0], [False, False, 0], [False, True, 0], [False, True, 25], [True, False, 30]] | [[False, True, 0], [False, False, 0], [False, True, 0], [False, False, 0], [False, False, 0], [False, True, 0], [False, True, 25], [True, False, 30]] | Passed |
| control: scenario 2 | [[False, False, 0], [False, True, 0], [False, True, 0], [False, True, 0], [False, True, 25], [True, False, 30], [True, False, 30]] | [[False, False, 0], [False, True, 0], [False, True, 0], [False, True, 0], [False, True, 25], [True, False, 30], [True, False, 30]] | Passed |
| control: scenario 4 | [[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]] | [[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]] | Passed |
SHA-256 / 1c70c34814693bc1021ae0d4d5068c989d39025cb2c49d66644d9075b317d509
3 / The verified repair
Exit 0"""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: 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)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: interrupted timing restarts | [[False, True, 0], [False, True, 40], [False, False, 0], [False, True, 0], [False, True, 40], [True, False, 60]] | [[False, True, 0], [False, True, 40], [False, False, 0], [False, True, 0], [False, True, 40], [True, False, 60]] | Passed |
| regression: scenario 3 | [[False, True, 0], [False, True, 20], [False, False, 0], [False, True, 0], [False, True, 0], [False, False, 0], [False, True, 0]] | [[False, True, 0], [False, True, 20], [False, False, 0], [False, True, 0], [False, True, 0], [False, False, 0], [False, True, 0]] | Passed |
| control: preset reached exactly | [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]] | [[False, True, 0], [False, True, 50], [True, False, 100], [True, False, 100]] | Passed |
| control: zero preset | [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]] | [[False, False, 0], [True, False, 0], [False, False, 0], [True, False, 0]] | Passed |
| regression: long hold after done | [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]] | [[False, True, 0], [False, True, 30], [True, False, 50], [True, False, 50], [False, False, 0]] | Passed |
| control: scenario 1 | [[False, True, 0], [False, False, 0], [False, True, 0], [False, False, 0], [False, False, 0], [False, True, 0], [False, True, 25], [True, False, 30]] | [[False, True, 0], [False, False, 0], [False, True, 0], [False, False, 0], [False, False, 0], [False, True, 0], [False, True, 25], [True, False, 30]] | Passed |
| control: scenario 2 | [[False, False, 0], [False, True, 0], [False, True, 0], [False, True, 0], [False, True, 25], [True, False, 30], [True, False, 30]] | [[False, False, 0], [False, True, 0], [False, True, 0], [False, True, 0], [False, True, 25], [True, False, 30], [True, False, 30]] | Passed |
| control: scenario 4 | [[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]] | [[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]] | Passed |
SHA-256 / c9f740b9f17bbd7409e2a479b6698563074e2e9453cec2f677cb1046ee5a0030
Verification & scope
A deterministic bounded teaching model of one PLC instruction or rung pattern evaluated scan by scan. The stated contract is a stipulated toy convention, not a claim of conformance to any vendor controller or IEC 61131-3 runtime. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:40.137583+00:00.
Case digest / f654086193f8f4f4952c90f393f40883ea88826d2b0fd47f212b87166fb6957f