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

N = 1
observations = []
def solve(interval, max_minutes, samples):
    acc = 0
    defrost_min = None
    out = []
    for running, coil, outdoor in samples:
        if defrost_min is not None:
            defrost_min += 1
            if coil >= 57 or defrost_min >= max_minutes:
                defrost_min = None
                out.append('defrost')
            else:
                out.append('defrost')
            continue
        if running and coil <= 32:
            acc += 1
        if acc >= interval and outdoor <= 50:
            acc = 0
            defrost_min = 0
            out.append('defrost')
            continue
        out.append('heat' if running else 'off')
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: two defrosts',
   [3,
    4,
    [[True, 30, 20],
     [True, 30, 20],
     [False, 30, 20],
     [True, 32, 20],
     [True, 40, 20],
     [True, 45, 20],
     [True, 57, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20]]],
   ['heat',
    'heat',
    'off',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat']],
  ['regression: scenario 8',
   [3,
    4,
    [[True, 28, 50],
     [True, 28, 51],
     [True, 28, 60],
     [True, 28, 60],
     [True, 28, 51],
     [True, 28, 50],
     [True, 28, 51],
     [True, 28, 50],
     [True, 28, 50],
     [False, 20, 35],
     [True, 20, 51],
     [True, 56, 60],
     [False, 28, 60],
     [True, 28, 50],
     [False, 32, 35]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'off',
    'heat',
    'heat',
    'off',
    'heat',
    'off']],
  ['regression: warm outdoor inhibits',
   [2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
   ['heat', 'heat', 'defrost', 'heat', 'heat']],
  ['control: dry coil runtime',
   [2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
   ['heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: exact termination temperature',
   [1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
   ['defrost', 'defrost', 'heat', 'off', 'defrost']],
  ['control: scenario 1',
   [3,
    3,
    [[True, 40, 35],
     [True, 40, 50],
     [True, 40, 51],
     [True, 40, 51],
     [True, 40, 50],
     [True, 40, 50],
     [False, 20, 35],
     [False, 20, 51],
     [True, 20, 50],
     [True, 50, 20],
     [True, 50, 50],
     [True, 56, 50],
     [True, 40, 50],
     [True, 40, 50],
     [False, 40, 51],
     [True, 40, 50],
     [False, 20, 51],
     [False, 20, 60],
     [True, 57, 51],
     [False, 57, 51]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'off',
    'off',
    'heat',
    'off']],
  ['regression: scenario 2',
   [4,
    3,
    [[True, 33, 60],
     [False, 57, 20],
     [True, 57, 50],
     [True, 60, 20],
     [True, 60, 35],
     [True, 60, 50],
     [True, 28, 50],
     [True, 28, 20],
     [True, 28, 20],
     [False, 28, 50],
     [True, 28, 51],
     [True, 28, 35],
     [True, 28, 60],
     [True, 28, 50],
     [True, 40, 50],
     [True, 40, 50],
     [False, 40, 60]]],
   ['heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'off']],
  ['regression: scenario 3',
   [5,
    3,
    [[True, 20, 20],
     [True, 20, 50],
     [True, 20, 50],
     [True, 20, 50],
     [True, 20, 35],
     [True, 40, 50],
     [False, 40, 20],
     [True, 40, 50],
     [True, 40, 50],
     [True, 33, 60],
     [False, 33, 60],
     [True, 60, 50]]],
   ['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'off', 'heat']]],
 [['regression: warm outdoor inhibits',
   [2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
   ['heat', 'heat', 'defrost', 'heat', 'heat']],
  ['regression: scenario 5',
   [3,
    6,
    [[True, 32, 51],
     [True, 32, 50],
     [True, 32, 50],
     [True, 40, 20],
     [True, 40, 50],
     [True, 50, 51],
     [False, 57, 50],
     [True, 57, 50],
     [False, 60, 35],
     [False, 60, 35],
     [True, 60, 60],
     [True, 60, 60],
     [False, 28, 50],
     [True, 50, 60],
     [True, 60, 50],
     [True, 60, 20],
     [True, 60, 51],
     [True, 60, 50],
     [False, 60, 50],
     [True, 60, 35]]],
   ['heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'off',
    'heat',
    'off',
    'off',
    'heat',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat']],
  ['regression: two defrosts',
   [3,
    4,
    [[True, 30, 20],
     [True, 30, 20],
     [False, 30, 20],
     [True, 32, 20],
     [True, 40, 20],
     [True, 45, 20],
     [True, 57, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20]]],
   ['heat',
    'heat',
    'off',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat']],
  ['control: dry coil runtime',
   [2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
   ['heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: exact termination temperature',
   [1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
   ['defrost', 'defrost', 'heat', 'off', 'defrost']],
  ['regression: scenario 1',
   [3,
    3,
    [[True, 28, 20],
     [True, 28, 50],
     [True, 32, 50],
     [False, 32, 35],
     [True, 60, 20],
     [True, 60, 35],
     [True, 60, 50],
     [True, 60, 50],
     [True, 57, 50],
     [True, 57, 50],
     [True, 60, 60],
     [False, 60, 50],
     [True, 60, 35],
     [True, 33, 50]]],
   ['heat',
    'heat',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'heat']],
  ['regression: scenario 2',
   [4,
    4,
    [[True, 40, 50],
     [True, 40, 35],
     [True, 40, 60],
     [False, 56, 60],
     [True, 56, 35],
     [True, 50, 50],
     [True, 32, 35],
     [True, 32, 51],
     [True, 32, 20],
     [True, 32, 51],
     [True, 32, 60],
     [True, 57, 35],
     [True, 32, 50],
     [True, 32, 35],
     [True, 20, 35],
     [True, 50, 35],
     [True, 57, 35],
     [True, 57, 51],
     [False, 57, 50]]],
   ['heat',
    'heat',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'off']],
  ['control: scenario 3',
   [3,
    6,
    [[False, 56, 51],
     [True, 56, 35],
     [False, 56, 35],
     [True, 56, 35],
     [True, 56, 35],
     [True, 33, 50],
     [True, 33, 20],
     [True, 33, 50],
     [False, 33, 60],
     [True, 33, 35],
     [True, 33, 35],
     [True, 33, 50],
     [True, 33, 60],
     [True, 33, 35],
     [True, 33, 35],
     [True, 20, 50],
     [True, 20, 51]]],
   ['off',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat']]],
 [['regression: exact termination temperature',
   [1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
   ['defrost', 'defrost', 'heat', 'off', 'defrost']],
  ['regression: scenario 23',
   [3,
    4,
    [[True, 20, 60],
     [True, 20, 20],
     [True, 20, 50],
     [False, 57, 51],
     [True, 60, 50],
     [True, 60, 51],
     [True, 60, 50],
     [True, 60, 20],
     [True, 60, 51],
     [True, 60, 50],
     [True, 60, 20],
     [True, 40, 20],
     [True, 40, 51],
     [True, 40, 60]]],
   ['heat',
    'heat',
    'defrost',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat']],
  ['regression: two defrosts',
   [3,
    4,
    [[True, 30, 20],
     [True, 30, 20],
     [False, 30, 20],
     [True, 32, 20],
     [True, 40, 20],
     [True, 45, 20],
     [True, 57, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20]]],
   ['heat',
    'heat',
    'off',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat']],
  ['regression: warm outdoor inhibits',
   [2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
   ['heat', 'heat', 'defrost', 'heat', 'heat']],
  ['control: dry coil runtime',
   [2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
   ['heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: scenario 1',
   [4,
    6,
    [[True, 33, 20],
     [True, 28, 50],
     [True, 56, 51],
     [True, 33, 51],
     [True, 28, 35],
     [False, 28, 50],
     [True, 28, 60],
     [True, 28, 20],
     [True, 40, 50],
     [True, 40, 35],
     [True, 40, 51],
     [True, 40, 50],
     [True, 28, 60],
     [True, 28, 50],
     [True, 50, 35],
     [True, 60, 50],
     [True, 57, 20],
     [True, 40, 50]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat']],
  ['control: scenario 2',
   [4,
    3,
    [[True, 32, 20],
     [True, 57, 60],
     [True, 57, 60],
     [True, 57, 20],
     [False, 40, 51],
     [True, 50, 50],
     [True, 50, 51],
     [True, 50, 50],
     [True, 56, 60],
     [True, 40, 20],
     [False, 40, 35],
     [True, 50, 35],
     [False, 50, 51],
     [False, 50, 35],
     [True, 57, 35],
     [True, 57, 20],
     [True, 57, 20],
     [True, 57, 50],
     [True, 57, 60]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'off',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat']],
  ['regression: scenario 3',
   [3,
    6,
    [[True, 20, 60],
     [True, 33, 20],
     [True, 33, 60],
     [True, 33, 51],
     [True, 33, 35],
     [True, 32, 50],
     [True, 32, 35],
     [True, 32, 35],
     [True, 32, 60],
     [True, 32, 60],
     [False, 32, 60],
     [True, 32, 35],
     [False, 32, 50],
     [True, 40, 50]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'off',
    'heat']]],
 [['regression: scenario 3',
   [5,
    4,
    [[False, 32, 51],
     [False, 32, 50],
     [True, 32, 20],
     [True, 32, 50],
     [True, 32, 50],
     [True, 32, 51],
     [True, 32, 20],
     [True, 56, 50],
     [False, 56, 50],
     [True, 56, 51],
     [True, 56, 51],
     [False, 56, 35],
     [True, 20, 20],
     [True, 20, 35],
     [True, 20, 60],
     [True, 20, 50]]],
   ['off',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat']],
  ['regression: scenario 22',
   [5,
    4,
    [[True, 28, 20],
     [True, 28, 20],
     [True, 28, 50],
     [True, 28, 60],
     [True, 28, 51],
     [True, 28, 50],
     [True, 28, 20],
     [True, 28, 50],
     [False, 57, 35],
     [True, 50, 20],
     [True, 50, 50],
     [True, 28, 50],
     [False, 28, 35],
     [True, 20, 50],
     [False, 20, 20],
     [True, 20, 50],
     [True, 40, 20],
     [True, 33, 35],
     [True, 33, 51],
     [False, 33, 20]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'off',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'off']],
  ['regression: two defrosts',
   [3,
    4,
    [[True, 30, 20],
     [True, 30, 20],
     [False, 30, 20],
     [True, 32, 20],
     [True, 40, 20],
     [True, 45, 20],
     [True, 57, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20]]],
   ['heat',
    'heat',
    'off',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat']],
  ['regression: warm outdoor inhibits',
   [2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
   ['heat', 'heat', 'defrost', 'heat', 'heat']],
  ['control: dry coil runtime',
   [2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
   ['heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: exact termination temperature',
   [1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
   ['defrost', 'defrost', 'heat', 'off', 'defrost']],
  ['control: scenario 1',
   [5,
    4,
    [[True, 57, 60],
     [True, 57, 50],
     [True, 57, 50],
     [True, 57, 35],
     [True, 33, 50],
     [True, 33, 50],
     [True, 32, 50],
     [True, 50, 51],
     [True, 50, 51],
     [False, 50, 20],
     [False, 33, 50],
     [True, 56, 20],
     [True, 32, 60],
     [True, 32, 35],
     [True, 32, 20]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'off',
    'heat',
    'heat',
    'heat',
    'heat']],
  ['control: scenario 2',
   [4,
    6,
    [[False, 28, 50],
     [True, 28, 51],
     [True, 28, 35],
     [True, 28, 50],
     [True, 57, 50],
     [True, 57, 20],
     [True, 57, 50],
     [True, 57, 50],
     [True, 56, 50],
     [True, 56, 35],
     [True, 56, 51],
     [True, 56, 50]]],
   ['off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat']]],
 [['regression: scenario 5',
   [5,
    4,
    [[True, 28, 51],
     [True, 28, 51],
     [False, 28, 50],
     [True, 28, 35],
     [True, 28, 35],
     [True, 40, 60],
     [True, 56, 20],
     [False, 40, 35],
     [False, 40, 50],
     [True, 40, 50],
     [True, 40, 50],
     [True, 40, 35],
     [True, 40, 50],
     [True, 28, 51],
     [False, 28, 50],
     [True, 28, 50],
     [True, 56, 35],
     [True, 33, 35],
     [True, 50, 50],
     [False, 50, 50],
     [True, 50, 50]]],
   ['heat',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'off',
    'heat']],
  ['regression: scenario 43',
   [4,
    3,
    [[True, 40, 20],
     [False, 40, 50],
     [True, 60, 51],
     [True, 60, 51],
     [True, 60, 20],
     [True, 32, 51],
     [True, 32, 35],
     [True, 32, 50],
     [True, 32, 51],
     [True, 32, 50],
     [True, 32, 51],
     [True, 32, 60],
     [False, 32, 60],
     [True, 32, 50],
     [True, 32, 50],
     [False, 32, 20],
     [True, 60, 20]]],
   ['heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'off',
    'heat',
    'heat',
    'off',
    'heat']],
  ['regression: two defrosts',
   [3,
    4,
    [[True, 30, 20],
     [True, 30, 20],
     [False, 30, 20],
     [True, 32, 20],
     [True, 40, 20],
     [True, 45, 20],
     [True, 57, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20]]],
   ['heat',
    'heat',
    'off',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat']],
  ['regression: warm outdoor inhibits',
   [2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
   ['heat', 'heat', 'defrost', 'heat', 'heat']],
  ['control: dry coil runtime',
   [2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
   ['heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: exact termination temperature',
   [1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
   ['defrost', 'defrost', 'heat', 'off', 'defrost']],
  ['control: scenario 1',
   [4,
    6,
    [[True, 32, 50],
     [True, 50, 50],
     [True, 50, 35],
     [True, 57, 51],
     [True, 57, 20],
     [False, 57, 51],
     [True, 57, 50],
     [True, 57, 51],
     [True, 32, 50],
     [True, 32, 51],
     [True, 32, 50],
     [False, 28, 50]]],
   ['heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: scenario 2',
   [3,
    4,
    [[True, 32, 35],
     [True, 32, 35],
     [True, 33, 60],
     [True, 33, 50],
     [True, 33, 60],
     [True, 57, 51],
     [True, 20, 60],
     [True, 20, 50],
     [True, 33, 50],
     [False, 33, 51],
     [False, 33, 20],
     [True, 33, 20],
     [True, 40, 50],
     [True, 40, 50],
     [True, 40, 35],
     [True, 40, 35],
     [True, 40, 51],
     [True, 28, 35],
     [True, 28, 51],
     [True, 33, 60],
     [False, 33, 60],
     [True, 56, 51],
     [True, 56, 60],
     [False, 56, 60]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'heat',
    'off']]]]
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(interval, max_minutes, samples):
    acc = 0
    defrost_min = None
    out = []
    for running, coil, outdoor in samples:
        if defrost_min is not None:
            defrost_min += 1
            if coil >= 57 or defrost_min >= max_minutes:
                defrost_min = None
                out.append('heat')
            else:
                out.append('defrost')
            continue
        if running and coil <= 32:
            acc += 1
        if acc >= interval and outdoor <= 50:
            acc = 0
            defrost_min = 0
            out.append('defrost')
            continue
        out.append('heat' if running else 'off')
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: two defrosts',
   [3,
    4,
    [[True, 30, 20],
     [True, 30, 20],
     [False, 30, 20],
     [True, 32, 20],
     [True, 40, 20],
     [True, 45, 20],
     [True, 57, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20]]],
   ['heat',
    'heat',
    'off',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat']],
  ['regression: scenario 8',
   [3,
    4,
    [[True, 28, 50],
     [True, 28, 51],
     [True, 28, 60],
     [True, 28, 60],
     [True, 28, 51],
     [True, 28, 50],
     [True, 28, 51],
     [True, 28, 50],
     [True, 28, 50],
     [False, 20, 35],
     [True, 20, 51],
     [True, 56, 60],
     [False, 28, 60],
     [True, 28, 50],
     [False, 32, 35]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'off',
    'heat',
    'heat',
    'off',
    'heat',
    'off']],
  ['regression: warm outdoor inhibits',
   [2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
   ['heat', 'heat', 'defrost', 'heat', 'heat']],
  ['control: dry coil runtime',
   [2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
   ['heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: exact termination temperature',
   [1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
   ['defrost', 'defrost', 'heat', 'off', 'defrost']],
  ['control: scenario 1',
   [3,
    3,
    [[True, 40, 35],
     [True, 40, 50],
     [True, 40, 51],
     [True, 40, 51],
     [True, 40, 50],
     [True, 40, 50],
     [False, 20, 35],
     [False, 20, 51],
     [True, 20, 50],
     [True, 50, 20],
     [True, 50, 50],
     [True, 56, 50],
     [True, 40, 50],
     [True, 40, 50],
     [False, 40, 51],
     [True, 40, 50],
     [False, 20, 51],
     [False, 20, 60],
     [True, 57, 51],
     [False, 57, 51]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'off',
    'off',
    'heat',
    'off']],
  ['regression: scenario 2',
   [4,
    3,
    [[True, 33, 60],
     [False, 57, 20],
     [True, 57, 50],
     [True, 60, 20],
     [True, 60, 35],
     [True, 60, 50],
     [True, 28, 50],
     [True, 28, 20],
     [True, 28, 20],
     [False, 28, 50],
     [True, 28, 51],
     [True, 28, 35],
     [True, 28, 60],
     [True, 28, 50],
     [True, 40, 50],
     [True, 40, 50],
     [False, 40, 60]]],
   ['heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'off']],
  ['regression: scenario 3',
   [5,
    3,
    [[True, 20, 20],
     [True, 20, 50],
     [True, 20, 50],
     [True, 20, 50],
     [True, 20, 35],
     [True, 40, 50],
     [False, 40, 20],
     [True, 40, 50],
     [True, 40, 50],
     [True, 33, 60],
     [False, 33, 60],
     [True, 60, 50]]],
   ['heat', 'heat', 'heat', 'heat', 'defrost', 'defrost', 'defrost', 'heat', 'heat', 'heat', 'off', 'heat']]],
 [['regression: warm outdoor inhibits',
   [2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
   ['heat', 'heat', 'defrost', 'heat', 'heat']],
  ['regression: scenario 5',
   [3,
    6,
    [[True, 32, 51],
     [True, 32, 50],
     [True, 32, 50],
     [True, 40, 20],
     [True, 40, 50],
     [True, 50, 51],
     [False, 57, 50],
     [True, 57, 50],
     [False, 60, 35],
     [False, 60, 35],
     [True, 60, 60],
     [True, 60, 60],
     [False, 28, 50],
     [True, 50, 60],
     [True, 60, 50],
     [True, 60, 20],
     [True, 60, 51],
     [True, 60, 50],
     [False, 60, 50],
     [True, 60, 35]]],
   ['heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'off',
    'heat',
    'off',
    'off',
    'heat',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat']],
  ['regression: two defrosts',
   [3,
    4,
    [[True, 30, 20],
     [True, 30, 20],
     [False, 30, 20],
     [True, 32, 20],
     [True, 40, 20],
     [True, 45, 20],
     [True, 57, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20]]],
   ['heat',
    'heat',
    'off',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat']],
  ['control: dry coil runtime',
   [2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
   ['heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: exact termination temperature',
   [1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
   ['defrost', 'defrost', 'heat', 'off', 'defrost']],
  ['regression: scenario 1',
   [3,
    3,
    [[True, 28, 20],
     [True, 28, 50],
     [True, 32, 50],
     [False, 32, 35],
     [True, 60, 20],
     [True, 60, 35],
     [True, 60, 50],
     [True, 60, 50],
     [True, 57, 50],
     [True, 57, 50],
     [True, 60, 60],
     [False, 60, 50],
     [True, 60, 35],
     [True, 33, 50]]],
   ['heat',
    'heat',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'heat']],
  ['regression: scenario 2',
   [4,
    4,
    [[True, 40, 50],
     [True, 40, 35],
     [True, 40, 60],
     [False, 56, 60],
     [True, 56, 35],
     [True, 50, 50],
     [True, 32, 35],
     [True, 32, 51],
     [True, 32, 20],
     [True, 32, 51],
     [True, 32, 60],
     [True, 57, 35],
     [True, 32, 50],
     [True, 32, 35],
     [True, 20, 35],
     [True, 50, 35],
     [True, 57, 35],
     [True, 57, 51],
     [False, 57, 50]]],
   ['heat',
    'heat',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'off']],
  ['control: scenario 3',
   [3,
    6,
    [[False, 56, 51],
     [True, 56, 35],
     [False, 56, 35],
     [True, 56, 35],
     [True, 56, 35],
     [True, 33, 50],
     [True, 33, 20],
     [True, 33, 50],
     [False, 33, 60],
     [True, 33, 35],
     [True, 33, 35],
     [True, 33, 50],
     [True, 33, 60],
     [True, 33, 35],
     [True, 33, 35],
     [True, 20, 50],
     [True, 20, 51]]],
   ['off',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat']]],
 [['regression: exact termination temperature',
   [1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
   ['defrost', 'defrost', 'heat', 'off', 'defrost']],
  ['regression: scenario 23',
   [3,
    4,
    [[True, 20, 60],
     [True, 20, 20],
     [True, 20, 50],
     [False, 57, 51],
     [True, 60, 50],
     [True, 60, 51],
     [True, 60, 50],
     [True, 60, 20],
     [True, 60, 51],
     [True, 60, 50],
     [True, 60, 20],
     [True, 40, 20],
     [True, 40, 51],
     [True, 40, 60]]],
   ['heat',
    'heat',
    'defrost',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat']],
  ['regression: two defrosts',
   [3,
    4,
    [[True, 30, 20],
     [True, 30, 20],
     [False, 30, 20],
     [True, 32, 20],
     [True, 40, 20],
     [True, 45, 20],
     [True, 57, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20]]],
   ['heat',
    'heat',
    'off',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat']],
  ['regression: warm outdoor inhibits',
   [2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
   ['heat', 'heat', 'defrost', 'heat', 'heat']],
  ['control: dry coil runtime',
   [2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
   ['heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: scenario 1',
   [4,
    6,
    [[True, 33, 20],
     [True, 28, 50],
     [True, 56, 51],
     [True, 33, 51],
     [True, 28, 35],
     [False, 28, 50],
     [True, 28, 60],
     [True, 28, 20],
     [True, 40, 50],
     [True, 40, 35],
     [True, 40, 51],
     [True, 40, 50],
     [True, 28, 60],
     [True, 28, 50],
     [True, 50, 35],
     [True, 60, 50],
     [True, 57, 20],
     [True, 40, 50]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat']],
  ['control: scenario 2',
   [4,
    3,
    [[True, 32, 20],
     [True, 57, 60],
     [True, 57, 60],
     [True, 57, 20],
     [False, 40, 51],
     [True, 50, 50],
     [True, 50, 51],
     [True, 50, 50],
     [True, 56, 60],
     [True, 40, 20],
     [False, 40, 35],
     [True, 50, 35],
     [False, 50, 51],
     [False, 50, 35],
     [True, 57, 35],
     [True, 57, 20],
     [True, 57, 20],
     [True, 57, 50],
     [True, 57, 60]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'off',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat']],
  ['regression: scenario 3',
   [3,
    6,
    [[True, 20, 60],
     [True, 33, 20],
     [True, 33, 60],
     [True, 33, 51],
     [True, 33, 35],
     [True, 32, 50],
     [True, 32, 35],
     [True, 32, 35],
     [True, 32, 60],
     [True, 32, 60],
     [False, 32, 60],
     [True, 32, 35],
     [False, 32, 50],
     [True, 40, 50]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'off',
    'heat']]],
 [['regression: scenario 3',
   [5,
    4,
    [[False, 32, 51],
     [False, 32, 50],
     [True, 32, 20],
     [True, 32, 50],
     [True, 32, 50],
     [True, 32, 51],
     [True, 32, 20],
     [True, 56, 50],
     [False, 56, 50],
     [True, 56, 51],
     [True, 56, 51],
     [False, 56, 35],
     [True, 20, 20],
     [True, 20, 35],
     [True, 20, 60],
     [True, 20, 50]]],
   ['off',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat']],
  ['regression: scenario 22',
   [5,
    4,
    [[True, 28, 20],
     [True, 28, 20],
     [True, 28, 50],
     [True, 28, 60],
     [True, 28, 51],
     [True, 28, 50],
     [True, 28, 20],
     [True, 28, 50],
     [False, 57, 35],
     [True, 50, 20],
     [True, 50, 50],
     [True, 28, 50],
     [False, 28, 35],
     [True, 20, 50],
     [False, 20, 20],
     [True, 20, 50],
     [True, 40, 20],
     [True, 33, 35],
     [True, 33, 51],
     [False, 33, 20]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'off',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'off']],
  ['regression: two defrosts',
   [3,
    4,
    [[True, 30, 20],
     [True, 30, 20],
     [False, 30, 20],
     [True, 32, 20],
     [True, 40, 20],
     [True, 45, 20],
     [True, 57, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20]]],
   ['heat',
    'heat',
    'off',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat']],
  ['regression: warm outdoor inhibits',
   [2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
   ['heat', 'heat', 'defrost', 'heat', 'heat']],
  ['control: dry coil runtime',
   [2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
   ['heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: exact termination temperature',
   [1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
   ['defrost', 'defrost', 'heat', 'off', 'defrost']],
  ['control: scenario 1',
   [5,
    4,
    [[True, 57, 60],
     [True, 57, 50],
     [True, 57, 50],
     [True, 57, 35],
     [True, 33, 50],
     [True, 33, 50],
     [True, 32, 50],
     [True, 50, 51],
     [True, 50, 51],
     [False, 50, 20],
     [False, 33, 50],
     [True, 56, 20],
     [True, 32, 60],
     [True, 32, 35],
     [True, 32, 20]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'off',
    'heat',
    'heat',
    'heat',
    'heat']],
  ['control: scenario 2',
   [4,
    6,
    [[False, 28, 50],
     [True, 28, 51],
     [True, 28, 35],
     [True, 28, 50],
     [True, 57, 50],
     [True, 57, 20],
     [True, 57, 50],
     [True, 57, 50],
     [True, 56, 50],
     [True, 56, 35],
     [True, 56, 51],
     [True, 56, 50]]],
   ['off', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat', 'heat']]],
 [['regression: scenario 5',
   [5,
    4,
    [[True, 28, 51],
     [True, 28, 51],
     [False, 28, 50],
     [True, 28, 35],
     [True, 28, 35],
     [True, 40, 60],
     [True, 56, 20],
     [False, 40, 35],
     [False, 40, 50],
     [True, 40, 50],
     [True, 40, 50],
     [True, 40, 35],
     [True, 40, 50],
     [True, 28, 51],
     [False, 28, 50],
     [True, 28, 50],
     [True, 56, 35],
     [True, 33, 35],
     [True, 50, 50],
     [False, 50, 50],
     [True, 50, 50]]],
   ['heat',
    'heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'off',
    'heat']],
  ['regression: scenario 43',
   [4,
    3,
    [[True, 40, 20],
     [False, 40, 50],
     [True, 60, 51],
     [True, 60, 51],
     [True, 60, 20],
     [True, 32, 51],
     [True, 32, 35],
     [True, 32, 50],
     [True, 32, 51],
     [True, 32, 50],
     [True, 32, 51],
     [True, 32, 60],
     [False, 32, 60],
     [True, 32, 50],
     [True, 32, 50],
     [False, 32, 20],
     [True, 60, 20]]],
   ['heat',
    'off',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'off',
    'heat',
    'heat',
    'off',
    'heat']],
  ['regression: two defrosts',
   [3,
    4,
    [[True, 30, 20],
     [True, 30, 20],
     [False, 30, 20],
     [True, 32, 20],
     [True, 40, 20],
     [True, 45, 20],
     [True, 57, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20],
     [True, 20, 20]]],
   ['heat',
    'heat',
    'off',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat']],
  ['regression: warm outdoor inhibits',
   [2, 3, [[True, 30, 55], [True, 30, 55], [True, 30, 50], [True, 60, 50], [True, 30, 50]]],
   ['heat', 'heat', 'defrost', 'heat', 'heat']],
  ['control: dry coil runtime',
   [2, 3, [[True, 40, 20], [True, 33, 20], [True, 32, 20], [True, 31, 20], [True, 50, 20]]],
   ['heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: exact termination temperature',
   [1, 5, [[True, 30, 20], [True, 56, 20], [True, 57, 20], [False, 30, 20], [True, 30, 20]]],
   ['defrost', 'defrost', 'heat', 'off', 'defrost']],
  ['control: scenario 1',
   [4,
    6,
    [[True, 32, 50],
     [True, 50, 50],
     [True, 50, 35],
     [True, 57, 51],
     [True, 57, 20],
     [False, 57, 51],
     [True, 57, 50],
     [True, 57, 51],
     [True, 32, 50],
     [True, 32, 51],
     [True, 32, 50],
     [False, 28, 50]]],
   ['heat', 'heat', 'heat', 'heat', 'heat', 'off', 'heat', 'heat', 'heat', 'heat', 'defrost', 'defrost']],
  ['regression: scenario 2',
   [3,
    4,
    [[True, 32, 35],
     [True, 32, 35],
     [True, 33, 60],
     [True, 33, 50],
     [True, 33, 60],
     [True, 57, 51],
     [True, 20, 60],
     [True, 20, 50],
     [True, 33, 50],
     [False, 33, 51],
     [False, 33, 20],
     [True, 33, 20],
     [True, 40, 50],
     [True, 40, 50],
     [True, 40, 35],
     [True, 40, 35],
     [True, 40, 51],
     [True, 28, 35],
     [True, 28, 51],
     [True, 33, 60],
     [False, 33, 60],
     [True, 56, 51],
     [True, 56, 60],
     [False, 56, 60]]],
   ['heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'defrost',
    'defrost',
    'defrost',
    'defrost',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'heat',
    'off',
    'heat',
    'heat',
    'off']]]]
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:
Every defrost is reported one minute longer and the heating restart is delayed.

Heat pump time-temperature defrost sampled per minute (degrees F); samples are [compressor_running, coil_temp, outdoor_temp]. Compressor run minutes accumulate only while coil <= 32. When the accumulation reaches interval and outdoor <= 50, defrost starts that minute and the accumulation resets; otherwise the accumulation keeps growing. Defrost ends on the first later minute with coil >= 57 or when it has lasted max_minutes minutes; that minute reports normal operation. Return heat, off or defrost per minute.

split: open-access


meaning: Fixture-count band, not measured model difficulty

deps: stdlib

prompt:
Early Monday morning runs the Monday wake setpoint instead of Sunday night's sleep setpoint.

Programmable thermostat weekly schedule. schedule is an unordered list of [day 0=Monday..6, minute_of_day, setpoint]; queries are [day, minute]. The active setpoint is that of the latest event at or before the query time within the week; if none, the last event of the week carries over from the previous week. Return the active setpoint per query.

split: open-access


prompt:
At exactly the programmed time the thermostat still shows the previous period.

Programmable thermostat weekly schedule. schedule is an unordered list of [day 0=Monday..6, minute_of_day, setpoint]; queries are [day, minute]. The active setpoint is that of the latest event at or before the query time within the week; if none, the last event of the week carries over from the previous week. Return the active setpoint per query.

split: open-access


prompt:
A weekend event overrides weekday times because only the minute of day is compared.

Programmable thermostat weekly schedule. schedule is an unordered list of [day 0=Monday..6, minute_of_day, setpoint]; queries are [day, minute]. The active setpoint is that of the latest event at or before the query time within the week; if none, the last event of the week carries over from the previous week. Return the active setpoint per query.

split: open-access


prompt:
Editing an earlier period after a later one makes the lookup stop at the wrong event.

Programmable thermostat weekly schedule. schedule is an unordered list of [day 0=Monday..6, minute_of_day, setpoint]; queries are [day, minute]. The active setpoint is that of the latest event at or before the query time within the week; if none, the last event of the week carries over from the previous week. Return the active setpoint per query.

split: open-access


prompt:
A "hold until next period" never ends, while a permanent hold is dropped at the next program change.

Thermostat hold logic; samples are [schedule_period_id, scheduled_setpoint, action] where action is None, "resume", ["temp", sp] or ["perm", sp]. A hold setpoint is clamped to 50.0-90.0 F (500-900 tenths). A temporary hold lasts until the schedule period id changes from the one in which the hold was set; a permanent hold lasts until resume. A new hold of either kind replaces the current hold. Return the effective setpoint per sample.

split: open-access


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

N = 1
observations = []
def solve(samples):
    hold = None
    hold_period = None
    out = []
    for period, sched, action in samples:
        if action == 'resume':
            hold = None
        elif action is not None:
            kind, sp = action
            sp = max(500, min(900, sp))
            hold = [kind, sp]
            if hold_period is None:
                hold_period = period
        if hold is not None and hold[0] == 'temp' and period != hold_period:
            hold = None
        out.append(sched if hold is None else hold[1])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['regression: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[0, 700, ['perm', 690]],
     [0, 700, None],
     [0, 700, 'resume'],
     [1, 700, None],
     [1, 700, None],
     [2, 600, None],
     [2, 600, None],
     [3, 680, ['perm', 856]],
     [4, 620, ['perm', 777]],
     [4, 620, None],
     [4, 620, None],
     [5, 600, ['temp', 764]],
     [5, 600, None],
     [6, 600, None],
     [7, 600, ['temp', 726]],
     [7, 600, None]]],
   [690, 690, 700, 700, 700, 600, 600, 856, 777, 777, 777, 764, 764, 600, 726, 726]],
  ['control: scenario 2',
   [[[1, 620, None],
     [1, 620, ['perm', 540]],
     [1, 620, None],
     [1, 620, None],
     [1, 620, ['temp', 863]],
     [2, 600, None],
     [3, 700, ['perm', 476]],
     [3, 700, None],
     [3, 700, None]]],
   [620, 540, 540, 540, 863, 600, 500, 500, 500]],
  ['regression: scenario 3',
   [[[1, 620, ['temp', 657]],
     [1, 620, ['temp', 940]],
     [1, 620, None],
     [1, 620, None],
     [1, 620, None],
     [2, 700, 'resume'],
     [2, 700, ['temp', 641]],
     [3, 620, None]]],
   [657, 900, 900, 900, 900, 700, 641, 620]],
  ['control: scenario 4',
   [[[0, 700, ['temp', 891]],
     [0, 700, None],
     [0, 700, None],
     [0, 700, ['temp', 877]],
     [0, 700, None],
     [0, 700, None],
     [1, 600, None],
     [1, 600, 'resume'],
     [2, 620, ['perm', 514]]]],
   [891, 891, 891, 877, 877, 877, 600, 600, 514]]],
 [['regression: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[1, 700, 'resume'],
     [1, 700, ['perm', 548]],
     [1, 700, None],
     [1, 700, None],
     [2, 700, None],
     [3, 620, None],
     [4, 620, None],
     [5, 680, None],
     [5, 680, ['temp', 806]],
     [5, 680, None],
     [5, 680, None],
     [6, 700, None],
     [6, 700, None],
     [6, 700, None]]],
   [700, 548, 548, 548, 548, 548, 548, 548, 806, 806, 806, 700, 700, 700]],
  ['regression: scenario 2',
   [[[0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, ['temp', 520]],
     [0, 680, None],
     [1, 680, None],
     [2, 620, None],
     [3, 680, ['perm', 745]],
     [3, 680, None],
     [3, 680, None],
     [4, 680, None],
     [5, 700, ['temp', 765]],
     [5, 700, None]]],
   [680, 680, 680, 680, 680, 680, 520, 520, 680, 620, 745, 745, 745, 745, 765, 765]],
  ['control: scenario 3',
   [[[0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, ['perm', 700]],
     [0, 620, ['temp', 750]],
     [1, 620, None],
     [2, 620, None],
     [2, 620, None]]],
   [620, 620, 620, 620, 620, 700, 750, 620, 620, 620]],
  ['regression: scenario 4',
   [[[0, 680, None],
     [1, 600, ['temp', 779]],
     [1, 600, ['temp', 782]],
     [2, 680, None],
     [3, 700, ['perm', 454]],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, ['temp', 831]],
     [3, 700, None],
     [3, 700, None]]],
   [680, 779, 782, 680, 500, 500, 500, 500, 500, 831, 831, 831]]],
 [['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['regression: scenario 6',
   [[[1, 600, ['temp', 644]],
     [1, 600, None],
     [2, 700, 'resume'],
     [3, 600, None],
     [3, 600, None],
     [4, 620, ['temp', 652]],
     [5, 620, None],
     [5, 620, 'resume'],
     [5, 620, None],
     [5, 620, None],
     [6, 700, ['perm', 898]],
     [6, 700, None],
     [7, 680, None],
     [7, 680, ['temp', 919]]]],
   [644, 644, 700, 600, 600, 652, 620, 620, 620, 620, 898, 898, 898, 900]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['regression: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['control: scenario 1',
   [[[0, 620, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, None],
     [2, 680, ['temp', 617]],
     [2, 680, None],
     [2, 680, ['perm', 816]],
     [3, 620, ['perm', 930]],
     [3, 620, None]]],
   [620, 680, 680, 680, 617, 617, 816, 900, 900]],
  ['control: scenario 2',
   [[[0, 620, 'resume'],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, 'resume'],
     [1, 620, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [3, 620, None],
     [3, 620, ['perm', 870]],
     [3, 620, None]]],
   [620, 620, 620, 620, 620, 620, 700, 700, 700, 700, 620, 870, 870]],
  ['control: scenario 3',
   [[[0, 680, 'resume'],
     [1, 700, None],
     [1, 700, None],
     [1, 700, None],
     [2, 620, None],
     [2, 620, 'resume'],
     [2, 620, None],
     [2, 620, ['temp', 685]],
     [2, 620, ['perm', 890]],
     [2, 620, ['perm', 678]]]],
   [680, 700, 700, 700, 620, 620, 620, 685, 890, 678]]],
 [['regression: scenario 1',
   [[[1, 700, ['temp', 847]],
     [1, 700, None],
     [1, 700, None],
     [1, 700, 'resume'],
     [1, 700, None],
     [1, 700, None],
     [1, 700, ['perm', 465]],
     [1, 700, None],
     [2, 600, ['temp', 552]],
     [2, 600, None],
     [2, 600, ['temp', 898]]]],
   [847, 847, 847, 700, 700, 700, 500, 500, 552, 552, 898]],
  ['regression: scenario 5',
   [[[1, 600, ['perm', 826]],
     [2, 700, None],
     [2, 700, None],
     [3, 620, ['temp', 796]],
     [3, 620, None],
     [3, 620, ['perm', 703]],
     [3, 620, None],
     [3, 620, 'resume'],
     [3, 620, None],
     [4, 680, ['perm', 694]]]],
   [826, 826, 826, 796, 796, 703, 703, 620, 620, 694]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['regression: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 2',
   [[[0, 680, 'resume'],
     [0, 680, None],
     [0, 680, ['perm', 681]],
     [0, 680, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, ['temp', 832]],
     [1, 680, ['temp', 511]],
     [1, 680, ['perm', 779]],
     [1, 680, ['temp', 724]],
     [2, 700, 'resume'],
     [3, 680, None],
     [3, 680, 'resume']]],
   [680, 680, 681, 681, 681, 681, 681, 832, 511, 779, 724, 700, 680, 680]],
  ['control: scenario 3',
   [[[0, 680, None],
     [1, 680, None],
     [2, 600, 'resume'],
     [2, 600, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, 'resume'],
     [4, 600, None],
     [4, 600, None],
     [4, 600, None],
     [5, 620, ['temp', 645]],
     [6, 700, None]]],
   [680, 680, 600, 600, 700, 700, 700, 700, 600, 600, 600, 645, 700]]],
 [['regression: scenario 3',
   [[[0, 680, None],
     [0, 680, None],
     [1, 700, ['perm', 502]],
     [1, 700, None],
     [1, 700, None],
     [1, 700, None],
     [1, 700, None],
     [1, 700, None],
     [1, 700, ['perm', 754]],
     [1, 700, None],
     [2, 700, ['temp', 591]],
     [2, 700, None],
     [2, 700, None],
     [2, 700, ['temp', 502]],
     [3, 680, 'resume'],
     [3, 680, None]]],
   [680, 680, 502, 502, 502, 502, 502, 502, 754, 754, 591, 591, 591, 502, 680, 680]],
  ['regression: scenario 11',
   [[[0, 620, 'resume'],
     [0, 620, 'resume'],
     [0, 620, None],
     [0, 620, 'resume'],
     [1, 680, None],
     [1, 680, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, ['perm', 673]],
     [2, 700, None],
     [3, 620, None],
     [3, 620, None],
     [3, 620, None],
     [3, 620, ['temp', 583]]]],
   [620, 620, 620, 620, 680, 680, 700, 700, 700, 673, 673, 673, 673, 673, 583]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['regression: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[0, 700, None],
     [0, 700, None],
     [0, 700, None],
     [0, 700, ['perm', 578]],
     [1, 600, 'resume'],
     [2, 600, ['temp', 629]],
     [3, 700, None],
     [3, 700, ['perm', 796]],
     [3, 700, ['temp', 558]],
     [3, 700, None],
     [3, 700, None],
     [3, 700, ['temp', 796]],
     [4, 700, None],
     [4, 700, None],
     [4, 700, None],
     [4, 700, None]]],
   [700, 700, 700, 578, 600, 629, 700, 796, 558, 558, 558, 796, 700, 700, 700, 700]],
  ['control: scenario 2',
   [[[0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [1, 680, ['temp', 866]],
     [1, 680, None],
     [1, 680, ['temp', 591]],
     [1, 680, ['temp', 671]],
     [2, 700, None],
     [2, 700, None]]],
   [600, 600, 600, 600, 600, 866, 866, 591, 671, 700, 700]]]]
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(samples):
    hold = None
    hold_period = None
    out = []
    for period, sched, action in samples:
        if action == 'resume':
            hold = None
        elif action is not None:
            kind, sp = action
            sp = max(500, min(900, sp))
            hold = [kind, sp]
            hold_period = period if kind == 'perm' else (hold_period or period)
        if hold is not None and hold[0] == 'temp' and period != hold_period:
            hold = None
        out.append(sched if hold is None else hold[1])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['regression: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[0, 700, ['perm', 690]],
     [0, 700, None],
     [0, 700, 'resume'],
     [1, 700, None],
     [1, 700, None],
     [2, 600, None],
     [2, 600, None],
     [3, 680, ['perm', 856]],
     [4, 620, ['perm', 777]],
     [4, 620, None],
     [4, 620, None],
     [5, 600, ['temp', 764]],
     [5, 600, None],
     [6, 600, None],
     [7, 600, ['temp', 726]],
     [7, 600, None]]],
   [690, 690, 700, 700, 700, 600, 600, 856, 777, 777, 777, 764, 764, 600, 726, 726]],
  ['control: scenario 2',
   [[[1, 620, None],
     [1, 620, ['perm', 540]],
     [1, 620, None],
     [1, 620, None],
     [1, 620, ['temp', 863]],
     [2, 600, None],
     [3, 700, ['perm', 476]],
     [3, 700, None],
     [3, 700, None]]],
   [620, 540, 540, 540, 863, 600, 500, 500, 500]],
  ['regression: scenario 3',
   [[[1, 620, ['temp', 657]],
     [1, 620, ['temp', 940]],
     [1, 620, None],
     [1, 620, None],
     [1, 620, None],
     [2, 700, 'resume'],
     [2, 700, ['temp', 641]],
     [3, 620, None]]],
   [657, 900, 900, 900, 900, 700, 641, 620]],
  ['control: scenario 4',
   [[[0, 700, ['temp', 891]],
     [0, 700, None],
     [0, 700, None],
     [0, 700, ['temp', 877]],
     [0, 700, None],
     [0, 700, None],
     [1, 600, None],
     [1, 600, 'resume'],
     [2, 620, ['perm', 514]]]],
   [891, 891, 891, 877, 877, 877, 600, 600, 514]]],
 [['regression: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[1, 700, 'resume'],
     [1, 700, ['perm', 548]],
     [1, 700, None],
     [1, 700, None],
     [2, 700, None],
     [3, 620, None],
     [4, 620, None],
     [5, 680, None],
     [5, 680, ['temp', 806]],
     [5, 680, None],
     [5, 680, None],
     [6, 700, None],
     [6, 700, None],
     [6, 700, None]]],
   [700, 548, 548, 548, 548, 548, 548, 548, 806, 806, 806, 700, 700, 700]],
  ['regression: scenario 2',
   [[[0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, ['temp', 520]],
     [0, 680, None],
     [1, 680, None],
     [2, 620, None],
     [3, 680, ['perm', 745]],
     [3, 680, None],
     [3, 680, None],
     [4, 680, None],
     [5, 700, ['temp', 765]],
     [5, 700, None]]],
   [680, 680, 680, 680, 680, 680, 520, 520, 680, 620, 745, 745, 745, 745, 765, 765]],
  ['control: scenario 3',
   [[[0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, ['perm', 700]],
     [0, 620, ['temp', 750]],
     [1, 620, None],
     [2, 620, None],
     [2, 620, None]]],
   [620, 620, 620, 620, 620, 700, 750, 620, 620, 620]],
  ['regression: scenario 4',
   [[[0, 680, None],
     [1, 600, ['temp', 779]],
     [1, 600, ['temp', 782]],
     [2, 680, None],
     [3, 700, ['perm', 454]],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, ['temp', 831]],
     [3, 700, None],
     [3, 700, None]]],
   [680, 779, 782, 680, 500, 500, 500, 500, 500, 831, 831, 831]]],
 [['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['regression: scenario 6',
   [[[1, 600, ['temp', 644]],
     [1, 600, None],
     [2, 700, 'resume'],
     [3, 600, None],
     [3, 600, None],
     [4, 620, ['temp', 652]],
     [5, 620, None],
     [5, 620, 'resume'],
     [5, 620, None],
     [5, 620, None],
     [6, 700, ['perm', 898]],
     [6, 700, None],
     [7, 680, None],
     [7, 680, ['temp', 919]]]],
   [644, 644, 700, 600, 600, 652, 620, 620, 620, 620, 898, 898, 898, 900]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['regression: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['control: scenario 1',
   [[[0, 620, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, None],
     [2, 680, ['temp', 617]],
     [2, 680, None],
     [2, 680, ['perm', 816]],
     [3, 620, ['perm', 930]],
     [3, 620, None]]],
   [620, 680, 680, 680, 617, 617, 816, 900, 900]],
  ['control: scenario 2',
   [[[0, 620, 'resume'],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, 'resume'],
     [1, 620, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [3, 620, None],
     [3, 620, ['perm', 870]],
     [3, 620, None]]],
   [620, 620, 620, 620, 620, 620, 700, 700, 700, 700, 620, 870, 870]],
  ['control: scenario 3',
   [[[0, 680, 'resume'],
     [1, 700, None],
     [1, 700, None],
     [1, 700, None],
     [2, 620, None],
     [2, 620, 'resume'],
     [2, 620, None],
     [2, 620, ['temp', 685]],
     [2, 620, ['perm', 890]],
     [2, 620, ['perm', 678]]]],
   [680, 700, 700, 700, 620, 620, 620, 685, 890, 678]]],
 [['regression: scenario 1',
   [[[1, 700, ['temp', 847]],
     [1, 700, None],
     [1, 700, None],
     [1, 700, 'resume'],
     [1, 700, None],
     [1, 700, None],
     [1, 700, ['perm', 465]],
     [1, 700, None],
     [2, 600, ['temp', 552]],
     [2, 600, None],
     [2, 600, ['temp', 898]]]],
   [847, 847, 847, 700, 700, 700, 500, 500, 552, 552, 898]],
  ['regression: scenario 5',
   [[[1, 600, ['perm', 826]],
     [2, 700, None],
     [2, 700, None],
     [3, 620, ['temp', 796]],
     [3, 620, None],
     [3, 620, ['perm', 703]],
     [3, 620, None],
     [3, 620, 'resume'],
     [3, 620, None],
     [4, 680, ['perm', 694]]]],
   [826, 826, 826, 796, 796, 703, 703, 620, 620, 694]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['regression: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 2',
   [[[0, 680, 'resume'],
     [0, 680, None],
     [0, 680, ['perm', 681]],
     [0, 680, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, ['temp', 832]],
     [1, 680, ['temp', 511]],
     [1, 680, ['perm', 779]],
     [1, 680, ['temp', 724]],
     [2, 700, 'resume'],
     [3, 680, None],
     [3, 680, 'resume']]],
   [680, 680, 681, 681, 681, 681, 681, 832, 511, 779, 724, 700, 680, 680]],
  ['control: scenario 3',
   [[[0, 680, None],
     [1, 680, None],
     [2, 600, 'resume'],
     [2, 600, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, 'resume'],
     [4, 600, None],
     [4, 600, None],
     [4, 600, None],
     [5, 620, ['temp', 645]],
     [6, 700, None]]],
   [680, 680, 600, 600, 700, 700, 700, 700, 600, 600, 600, 645, 700]]],
 [['regression: scenario 3',
   [[[0, 680, None],
     [0, 680, None],
     [1, 700, ['perm', 502]],
     [1, 700, None],
     [1, 700, None],
     [1, 700, None],
     [1, 700, None],
     [1, 700, None],
     [1, 700, ['perm', 754]],
     [1, 700, None],
     [2, 700, ['temp', 591]],
     [2, 700, None],
     [2, 700, None],
     [2, 700, ['temp', 502]],
     [3, 680, 'resume'],
     [3, 680, None]]],
   [680, 680, 502, 502, 502, 502, 502, 502, 754, 754, 591, 591, 591, 502, 680, 680]],
  ['regression: scenario 11',
   [[[0, 620, 'resume'],
     [0, 620, 'resume'],
     [0, 620, None],
     [0, 620, 'resume'],
     [1, 680, None],
     [1, 680, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, ['perm', 673]],
     [2, 700, None],
     [3, 620, None],
     [3, 620, None],
     [3, 620, None],
     [3, 620, ['temp', 583]]]],
   [620, 620, 620, 620, 680, 680, 700, 700, 700, 673, 673, 673, 673, 673, 583]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['regression: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[0, 700, None],
     [0, 700, None],
     [0, 700, None],
     [0, 700, ['perm', 578]],
     [1, 600, 'resume'],
     [2, 600, ['temp', 629]],
     [3, 700, None],
     [3, 700, ['perm', 796]],
     [3, 700, ['temp', 558]],
     [3, 700, None],
     [3, 700, None],
     [3, 700, ['temp', 796]],
     [4, 700, None],
     [4, 700, None],
     [4, 700, None],
     [4, 700, None]]],
   [700, 700, 700, 578, 600, 629, 700, 796, 558, 558, 558, 796, 700, 700, 700, 700]],
  ['control: scenario 2',
   [[[0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [1, 680, ['temp', 866]],
     [1, 680, None],
     [1, 680, ['temp', 591]],
     [1, 680, ['temp', 671]],
     [2, 700, None],
     [2, 700, None]]],
   [600, 600, 600, 600, 600, 866, 866, 591, 671, 700, 700]]]]
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 temporary hold set in a later period expires immediately.

Thermostat hold logic; samples are [schedule_period_id, scheduled_setpoint, action] where action is None, "resume", ["temp", sp] or ["perm", sp]. A hold setpoint is clamped to 50.0-90.0 F (500-900 tenths). A temporary hold lasts until the schedule period id changes from the one in which the hold was set; a permanent hold lasts until resume. A new hold of either kind replaces the current hold. Return the effective setpoint per sample.

split: open-access


prompt:
A remote or keypad hold can command 40 F or 95 F.

Thermostat hold logic; samples are [schedule_period_id, scheduled_setpoint, action] where action is None, "resume", ["temp", sp] or ["perm", sp]. A hold setpoint is clamped to 50.0-90.0 F (500-900 tenths). A temporary hold lasts until the schedule period id changes from the one in which the hold was set; a permanent hold lasts until resume. A new hold of either kind replaces the current hold. Return the effective setpoint per sample.

split: open-access


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

N = 1
observations = []
def solve(samples):
    hold = None
    hold_period = None
    out = []
    for period, sched, action in samples:
        if action == 'resume':
            hold = None
        elif action is not None:
            kind, sp = action
            sp = max(500, min(900, sp))
            hold = [kind if hold is None or hold[0] != 'perm' else 'perm', sp]
            hold_period = period
        if hold is not None and hold[0] == 'temp' and period != hold_period:
            hold = None
        out.append(sched if hold is None else hold[1])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[0, 700, ['perm', 690]],
     [0, 700, None],
     [0, 700, 'resume'],
     [1, 700, None],
     [1, 700, None],
     [2, 600, None],
     [2, 600, None],
     [3, 680, ['perm', 856]],
     [4, 620, ['perm', 777]],
     [4, 620, None],
     [4, 620, None],
     [5, 600, ['temp', 764]],
     [5, 600, None],
     [6, 600, None],
     [7, 600, ['temp', 726]],
     [7, 600, None]]],
   [690, 690, 700, 700, 700, 600, 600, 856, 777, 777, 777, 764, 764, 600, 726, 726]],
  ['regression: scenario 2',
   [[[1, 620, None],
     [1, 620, ['perm', 540]],
     [1, 620, None],
     [1, 620, None],
     [1, 620, ['temp', 863]],
     [2, 600, None],
     [3, 700, ['perm', 476]],
     [3, 700, None],
     [3, 700, None]]],
   [620, 540, 540, 540, 863, 600, 500, 500, 500]],
  ['control: scenario 3',
   [[[1, 620, ['temp', 657]],
     [1, 620, ['temp', 940]],
     [1, 620, None],
     [1, 620, None],
     [1, 620, None],
     [2, 700, 'resume'],
     [2, 700, ['temp', 641]],
     [3, 620, None]]],
   [657, 900, 900, 900, 900, 700, 641, 620]],
  ['control: scenario 4',
   [[[0, 700, ['temp', 891]],
     [0, 700, None],
     [0, 700, None],
     [0, 700, ['temp', 877]],
     [0, 700, None],
     [0, 700, None],
     [1, 600, None],
     [1, 600, 'resume'],
     [2, 620, ['perm', 514]]]],
   [891, 891, 891, 877, 877, 877, 600, 600, 514]]],
 [['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['regression: scenario 1',
   [[[1, 700, 'resume'],
     [1, 700, ['perm', 548]],
     [1, 700, None],
     [1, 700, None],
     [2, 700, None],
     [3, 620, None],
     [4, 620, None],
     [5, 680, None],
     [5, 680, ['temp', 806]],
     [5, 680, None],
     [5, 680, None],
     [6, 700, None],
     [6, 700, None],
     [6, 700, None]]],
   [700, 548, 548, 548, 548, 548, 548, 548, 806, 806, 806, 700, 700, 700]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['control: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 2',
   [[[0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, ['temp', 520]],
     [0, 680, None],
     [1, 680, None],
     [2, 620, None],
     [3, 680, ['perm', 745]],
     [3, 680, None],
     [3, 680, None],
     [4, 680, None],
     [5, 700, ['temp', 765]],
     [5, 700, None]]],
   [680, 680, 680, 680, 680, 680, 520, 520, 680, 620, 745, 745, 745, 745, 765, 765]],
  ['regression: scenario 3',
   [[[0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, ['perm', 700]],
     [0, 620, ['temp', 750]],
     [1, 620, None],
     [2, 620, None],
     [2, 620, None]]],
   [620, 620, 620, 620, 620, 700, 750, 620, 620, 620]],
  ['regression: scenario 4',
   [[[0, 680, None],
     [1, 600, ['temp', 779]],
     [1, 600, ['temp', 782]],
     [2, 680, None],
     [3, 700, ['perm', 454]],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, ['temp', 831]],
     [3, 700, None],
     [3, 700, None]]],
   [680, 779, 782, 680, 500, 500, 500, 500, 500, 831, 831, 831]]],
 [['regression: scenario 29',
   [[[0, 600, 'resume'],
     [0, 600, ['perm', 841]],
     [0, 600, None],
     [0, 600, None],
     [1, 700, None],
     [1, 700, None],
     [1, 700, ['temp', 875]],
     [2, 600, None],
     [2, 600, None],
     [3, 600, ['perm', 698]],
     [3, 600, None],
     [3, 600, None],
     [3, 600, ['perm', 580]],
     [4, 600, None],
     [4, 600, ['perm', 699]]]],
   [600, 841, 841, 841, 841, 841, 875, 600, 600, 698, 698, 698, 580, 580, 699]],
  ['regression: scenario 4',
   [[[1, 700, ['perm', 595]],
     [2, 600, None],
     [2, 600, ['perm', 854]],
     [3, 600, 'resume'],
     [3, 600, ['perm', 923]],
     [3, 600, ['perm', 783]],
     [3, 600, None],
     [3, 600, ['temp', 512]]]],
   [595, 595, 854, 600, 900, 783, 783, 512]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['control: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['control: scenario 1',
   [[[0, 620, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, None],
     [2, 680, ['temp', 617]],
     [2, 680, None],
     [2, 680, ['perm', 816]],
     [3, 620, ['perm', 930]],
     [3, 620, None]]],
   [620, 680, 680, 680, 617, 617, 816, 900, 900]],
  ['control: scenario 2',
   [[[0, 620, 'resume'],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, 'resume'],
     [1, 620, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [3, 620, None],
     [3, 620, ['perm', 870]],
     [3, 620, None]]],
   [620, 620, 620, 620, 620, 620, 700, 700, 700, 700, 620, 870, 870]]],
 [['regression: scenario 18',
   [[[0, 700, ['perm', 651]],
     [0, 700, None],
     [1, 700, ['temp', 753]],
     [2, 600, None],
     [2, 600, None],
     [3, 680, ['perm', 755]],
     [3, 680, 'resume'],
     [4, 700, None],
     [4, 700, None],
     [4, 700, ['temp', 927]]]],
   [651, 651, 753, 600, 600, 755, 680, 700, 700, 900]],
  ['regression: scenario 2',
   [[[0, 680, 'resume'],
     [0, 680, None],
     [0, 680, ['perm', 681]],
     [0, 680, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, ['temp', 832]],
     [1, 680, ['temp', 511]],
     [1, 680, ['perm', 779]],
     [1, 680, ['temp', 724]],
     [2, 700, 'resume'],
     [3, 680, None],
     [3, 680, 'resume']]],
   [680, 680, 681, 681, 681, 681, 681, 832, 511, 779, 724, 700, 680, 680]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['control: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[1, 700, ['temp', 847]],
     [1, 700, None],
     [1, 700, None],
     [1, 700, 'resume'],
     [1, 700, None],
     [1, 700, None],
     [1, 700, ['perm', 465]],
     [1, 700, None],
     [2, 600, ['temp', 552]],
     [2, 600, None],
     [2, 600, ['temp', 898]]]],
   [847, 847, 847, 700, 700, 700, 500, 500, 552, 552, 898]],
  ['control: scenario 3',
   [[[0, 680, None],
     [1, 680, None],
     [2, 600, 'resume'],
     [2, 600, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, 'resume'],
     [4, 600, None],
     [4, 600, None],
     [4, 600, None],
     [5, 620, ['temp', 645]],
     [6, 700, None]]],
   [680, 680, 600, 600, 700, 700, 700, 700, 600, 600, 600, 645, 700]]],
 [['regression: scenario 16',
   [[[0, 600, ['temp', 465]],
     [0, 600, ['perm', 908]],
     [0, 600, None],
     [1, 600, None],
     [2, 600, None],
     [2, 600, ['temp', 601]],
     [2, 600, None],
     [2, 600, None],
     [2, 600, None],
     [3, 700, None],
     [3, 700, ['perm', 598]],
     [3, 700, None],
     [4, 700, None],
     [4, 700, ['temp', 671]]]],
   [500, 900, 900, 900, 900, 601, 601, 601, 601, 700, 598, 598, 598, 671]],
  ['regression: scenario 5',
   [[[1, 680, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, 'resume'],
     [2, 700, 'resume'],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, ['perm', 533]],
     [2, 700, None],
     [2, 700, ['temp', 892]],
     [2, 700, ['temp', 859]],
     [2, 700, None]]],
   [680, 700, 700, 700, 700, 700, 700, 700, 700, 533, 533, 892, 859, 859]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['control: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[0, 700, None],
     [0, 700, None],
     [0, 700, None],
     [0, 700, ['perm', 578]],
     [1, 600, 'resume'],
     [2, 600, ['temp', 629]],
     [3, 700, None],
     [3, 700, ['perm', 796]],
     [3, 700, ['temp', 558]],
     [3, 700, None],
     [3, 700, None],
     [3, 700, ['temp', 796]],
     [4, 700, None],
     [4, 700, None],
     [4, 700, None],
     [4, 700, None]]],
   [700, 700, 700, 578, 600, 629, 700, 796, 558, 558, 558, 796, 700, 700, 700, 700]],
  ['control: scenario 2',
   [[[0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [1, 680, ['temp', 866]],
     [1, 680, None],
     [1, 680, ['temp', 591]],
     [1, 680, ['temp', 671]],
     [2, 700, None],
     [2, 700, None]]],
   [600, 600, 600, 600, 600, 866, 866, 591, 671, 700, 700]]]]
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(samples):
    hold = None
    hold_period = None
    out = []
    for period, sched, action in samples:
        if action == 'resume':
            hold = None
        elif action is not None:
            kind, sp = action
            sp = max(500, min(900, sp))
            if hold is None or hold[0] != 'perm' or kind == 'perm':
                hold = [kind, sp]
                hold_period = period
        if hold is not None and hold[0] == 'temp' and period != hold_period:
            hold = None
        out.append(sched if hold is None else hold[1])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[0, 700, ['perm', 690]],
     [0, 700, None],
     [0, 700, 'resume'],
     [1, 700, None],
     [1, 700, None],
     [2, 600, None],
     [2, 600, None],
     [3, 680, ['perm', 856]],
     [4, 620, ['perm', 777]],
     [4, 620, None],
     [4, 620, None],
     [5, 600, ['temp', 764]],
     [5, 600, None],
     [6, 600, None],
     [7, 600, ['temp', 726]],
     [7, 600, None]]],
   [690, 690, 700, 700, 700, 600, 600, 856, 777, 777, 777, 764, 764, 600, 726, 726]],
  ['regression: scenario 2',
   [[[1, 620, None],
     [1, 620, ['perm', 540]],
     [1, 620, None],
     [1, 620, None],
     [1, 620, ['temp', 863]],
     [2, 600, None],
     [3, 700, ['perm', 476]],
     [3, 700, None],
     [3, 700, None]]],
   [620, 540, 540, 540, 863, 600, 500, 500, 500]],
  ['control: scenario 3',
   [[[1, 620, ['temp', 657]],
     [1, 620, ['temp', 940]],
     [1, 620, None],
     [1, 620, None],
     [1, 620, None],
     [2, 700, 'resume'],
     [2, 700, ['temp', 641]],
     [3, 620, None]]],
   [657, 900, 900, 900, 900, 700, 641, 620]],
  ['control: scenario 4',
   [[[0, 700, ['temp', 891]],
     [0, 700, None],
     [0, 700, None],
     [0, 700, ['temp', 877]],
     [0, 700, None],
     [0, 700, None],
     [1, 600, None],
     [1, 600, 'resume'],
     [2, 620, ['perm', 514]]]],
   [891, 891, 891, 877, 877, 877, 600, 600, 514]]],
 [['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['regression: scenario 1',
   [[[1, 700, 'resume'],
     [1, 700, ['perm', 548]],
     [1, 700, None],
     [1, 700, None],
     [2, 700, None],
     [3, 620, None],
     [4, 620, None],
     [5, 680, None],
     [5, 680, ['temp', 806]],
     [5, 680, None],
     [5, 680, None],
     [6, 700, None],
     [6, 700, None],
     [6, 700, None]]],
   [700, 548, 548, 548, 548, 548, 548, 548, 806, 806, 806, 700, 700, 700]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['control: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 2',
   [[[0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, None],
     [0, 680, ['temp', 520]],
     [0, 680, None],
     [1, 680, None],
     [2, 620, None],
     [3, 680, ['perm', 745]],
     [3, 680, None],
     [3, 680, None],
     [4, 680, None],
     [5, 700, ['temp', 765]],
     [5, 700, None]]],
   [680, 680, 680, 680, 680, 680, 520, 520, 680, 620, 745, 745, 745, 745, 765, 765]],
  ['regression: scenario 3',
   [[[0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, ['perm', 700]],
     [0, 620, ['temp', 750]],
     [1, 620, None],
     [2, 620, None],
     [2, 620, None]]],
   [620, 620, 620, 620, 620, 700, 750, 620, 620, 620]],
  ['regression: scenario 4',
   [[[0, 680, None],
     [1, 600, ['temp', 779]],
     [1, 600, ['temp', 782]],
     [2, 680, None],
     [3, 700, ['perm', 454]],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, ['temp', 831]],
     [3, 700, None],
     [3, 700, None]]],
   [680, 779, 782, 680, 500, 500, 500, 500, 500, 831, 831, 831]]],
 [['regression: scenario 29',
   [[[0, 600, 'resume'],
     [0, 600, ['perm', 841]],
     [0, 600, None],
     [0, 600, None],
     [1, 700, None],
     [1, 700, None],
     [1, 700, ['temp', 875]],
     [2, 600, None],
     [2, 600, None],
     [3, 600, ['perm', 698]],
     [3, 600, None],
     [3, 600, None],
     [3, 600, ['perm', 580]],
     [4, 600, None],
     [4, 600, ['perm', 699]]]],
   [600, 841, 841, 841, 841, 841, 875, 600, 600, 698, 698, 698, 580, 580, 699]],
  ['regression: scenario 4',
   [[[1, 700, ['perm', 595]],
     [2, 600, None],
     [2, 600, ['perm', 854]],
     [3, 600, 'resume'],
     [3, 600, ['perm', 923]],
     [3, 600, ['perm', 783]],
     [3, 600, None],
     [3, 600, ['temp', 512]]]],
   [595, 595, 854, 600, 900, 783, 783, 512]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['control: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['control: scenario 1',
   [[[0, 620, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, None],
     [2, 680, ['temp', 617]],
     [2, 680, None],
     [2, 680, ['perm', 816]],
     [3, 620, ['perm', 930]],
     [3, 620, None]]],
   [620, 680, 680, 680, 617, 617, 816, 900, 900]],
  ['control: scenario 2',
   [[[0, 620, 'resume'],
     [0, 620, None],
     [0, 620, None],
     [0, 620, None],
     [0, 620, 'resume'],
     [1, 620, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [3, 620, None],
     [3, 620, ['perm', 870]],
     [3, 620, None]]],
   [620, 620, 620, 620, 620, 620, 700, 700, 700, 700, 620, 870, 870]]],
 [['regression: scenario 18',
   [[[0, 700, ['perm', 651]],
     [0, 700, None],
     [1, 700, ['temp', 753]],
     [2, 600, None],
     [2, 600, None],
     [3, 680, ['perm', 755]],
     [3, 680, 'resume'],
     [4, 700, None],
     [4, 700, None],
     [4, 700, ['temp', 927]]]],
   [651, 651, 753, 600, 600, 755, 680, 700, 700, 900]],
  ['regression: scenario 2',
   [[[0, 680, 'resume'],
     [0, 680, None],
     [0, 680, ['perm', 681]],
     [0, 680, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, None],
     [1, 680, ['temp', 832]],
     [1, 680, ['temp', 511]],
     [1, 680, ['perm', 779]],
     [1, 680, ['temp', 724]],
     [2, 700, 'resume'],
     [3, 680, None],
     [3, 680, 'resume']]],
   [680, 680, 681, 681, 681, 681, 681, 832, 511, 779, 724, 700, 680, 680]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['control: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[1, 700, ['temp', 847]],
     [1, 700, None],
     [1, 700, None],
     [1, 700, 'resume'],
     [1, 700, None],
     [1, 700, None],
     [1, 700, ['perm', 465]],
     [1, 700, None],
     [2, 600, ['temp', 552]],
     [2, 600, None],
     [2, 600, ['temp', 898]]]],
   [847, 847, 847, 700, 700, 700, 500, 500, 552, 552, 898]],
  ['control: scenario 3',
   [[[0, 680, None],
     [1, 680, None],
     [2, 600, 'resume'],
     [2, 600, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, None],
     [3, 700, 'resume'],
     [4, 600, None],
     [4, 600, None],
     [4, 600, None],
     [5, 620, ['temp', 645]],
     [6, 700, None]]],
   [680, 680, 600, 600, 700, 700, 700, 700, 600, 600, 600, 645, 700]]],
 [['regression: scenario 16',
   [[[0, 600, ['temp', 465]],
     [0, 600, ['perm', 908]],
     [0, 600, None],
     [1, 600, None],
     [2, 600, None],
     [2, 600, ['temp', 601]],
     [2, 600, None],
     [2, 600, None],
     [2, 600, None],
     [3, 700, None],
     [3, 700, ['perm', 598]],
     [3, 700, None],
     [4, 700, None],
     [4, 700, ['temp', 671]]]],
   [500, 900, 900, 900, 900, 601, 601, 601, 601, 700, 598, 598, 598, 671]],
  ['regression: scenario 5',
   [[[1, 680, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, 'resume'],
     [2, 700, 'resume'],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, None],
     [2, 700, ['perm', 533]],
     [2, 700, None],
     [2, 700, ['temp', 892]],
     [2, 700, ['temp', 859]],
     [2, 700, None]]],
   [680, 700, 700, 700, 700, 700, 700, 700, 700, 533, 533, 892, 859, 859]],
  ['regression: hold lifecycle',
   [[[1, 680, None],
     [1, 680, ['temp', 720]],
     [1, 680, None],
     [2, 620, None],
     [2, 620, ['perm', 950]],
     [3, 700, None],
     [3, 700, ['temp', 400]],
     [4, 650, None],
     [4, 650, 'resume']]],
   [680, 720, 720, 620, 900, 900, 500, 650, 650]],
  ['control: second temporary hold',
   [[[1, 680, ['temp', 700]], [2, 620, None], [3, 650, ['temp', 710]], [3, 650, None], [4, 600, None]]],
   [700, 620, 710, 710, 600]],
  ['regression: temporary over permanent',
   [[[1, 680, ['perm', 720]], [2, 620, ['temp', 690]], [2, 620, None], [3, 640, None]]],
   [720, 690, 690, 640]],
  ['control: clamp low', [[[1, 680, ['perm', 300]], [2, 620, None]]], [500, 500]],
  ['regression: scenario 1',
   [[[0, 700, None],
     [0, 700, None],
     [0, 700, None],
     [0, 700, ['perm', 578]],
     [1, 600, 'resume'],
     [2, 600, ['temp', 629]],
     [3, 700, None],
     [3, 700, ['perm', 796]],
     [3, 700, ['temp', 558]],
     [3, 700, None],
     [3, 700, None],
     [3, 700, ['temp', 796]],
     [4, 700, None],
     [4, 700, None],
     [4, 700, None],
     [4, 700, None]]],
   [700, 700, 700, 578, 600, 629, 700, 796, 558, 558, 558, 796, 700, 700, 700, 700]],
  ['control: scenario 2',
   [[[0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [0, 600, None],
     [1, 680, ['temp', 866]],
     [1, 680, None],
     [1, 680, ['temp', 591]],
     [1, 680, ['temp', 671]],
     [2, 700, None],
     [2, 700, None]]],
   [600, 600, 600, 600, 600, 866, 866, 591, 671, 700, 700]]]]
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:
Pressing the arrows during a vacation hold makes the new setpoint stick past the next period.

Thermostat hold logic; samples are [schedule_period_id, scheduled_setpoint, action] where action is None, "resume", ["temp", sp] or ["perm", sp]. A hold setpoint is clamped to 50.0-90.0 F (500-900 tenths). A temporary hold lasts until the schedule period id changes from the one in which the hold was set; a permanent hold lasts until resume. A new hold of either kind replaces the current hold. Return the effective setpoint per sample.

split: open-access


prompt:
The first press after switching to C sometimes leaves the displayed value unchanged or jumps the wrong way.

Thermostat setpoint keypad. The setpoint is stored in tenths F. In C mode the display shows the stored value converted to C and rounded half up to 0.5 C; a press moves the displayed value by 0.5 C and stores exactly 320 + half_degrees*9 tenths F. In F mode the display rounds half up to whole F and a press moves the whole-degree value by 1 F. After each press the stored value is clamped to 45.0-90.0 F. Return [display, stored_tenths_F] per press.

split: open-access


prompt:
A setpoint of 22.5 C is displayed as 22.1 C.

Thermostat setpoint keypad. The setpoint is stored in tenths F. In C mode the display shows the stored value converted to C and rounded half up to 0.5 C; a press moves the displayed value by 0.5 C and stores exactly 320 + half_degrees*9 tenths F. In F mode the display rounds half up to whole F and a press moves the whole-degree value by 1 F. After each press the stored value is clamped to 45.0-90.0 F. Return [display, stored_tenths_F] per press.

split: open-access


prompt:
Each arrow press in C mode jumps 1 C (1.8 F) instead of 0.5 C.

Thermostat setpoint keypad. The setpoint is stored in tenths F. In C mode the display shows the stored value converted to C and rounded half up to 0.5 C; a press moves the displayed value by 0.5 C and stores exactly 320 + half_degrees*9 tenths F. In F mode the display rounds half up to whole F and a press moves the whole-degree value by 1 F. After each press the stored value is clamped to 45.0-90.0 F. Return [display, stored_tenths_F] per press.

split: open-access


prompt:
Switching to Celsius lets the user walk the setpoint outside 45-90 F.

Thermostat setpoint keypad. The setpoint is stored in tenths F. In C mode the display shows the stored value converted to C and rounded half up to 0.5 C; a press moves the displayed value by 0.5 C and stores exactly 320 + half_degrees*9 tenths F. In F mode the display rounds half up to whole F and a press moves the whole-degree value by 1 F. After each press the stored value is clamped to 45.0-90.0 F. Return [display, stored_tenths_F] per press.

split: open-access


prompt:
Pressing up from a stored 72.5 F shows 73 instead of 74.

Thermostat setpoint keypad. The setpoint is stored in tenths F. In C mode the display shows the stored value converted to C and rounded half up to 0.5 C; a press moves the displayed value by 0.5 C and stores exactly 320 + half_degrees*9 tenths F. In F mode the display rounds half up to whole F and a press moves the whole-degree value by 1 F. After each press the stored value is clamped to 45.0-90.0 F. Return [display, stored_tenths_F] per press.

split: open-access