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

N = 1
observations = []
def solve(settings, samples):
    dehum = False
    cooling = False
    humid = False
    out = []
    for temp, rh, outdoor in samples:
        if dehum and rh <= settings['rh_sp']:
            dehum = False
        elif not dehum and rh > settings['rh_sp'] + 5:
            dehum = True
        eff = settings['cool_sp']
        if dehum:
            eff -= min(settings['max_overcool'], (rh - settings['rh_sp']) * 5)
        if cooling and temp <= eff:
            cooling = False
        elif not cooling and temp > eff + 10:
            cooling = True
        allowed = max(15, min(45, 40 + (outdoor - 20) // 10 * 5))
        target = settings['hum_sp']
        if outdoor >= 50:
            humid = False
        elif humid and rh >= target:
            humid = False
        elif not humid and rh < target - 3:
            humid = True
        out.append([cooling, eff, humid])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: summer then winter',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[765, 52, 80],
     [762, 58, 80],
     [745, 58, 80],
     [738, 50, 80],
     [700, 25, 10],
     [700, 29, 10],
     [700, 36, 10],
     [700, 10, -15]]],
   [[True, 750, False],
    [True, 720, False],
    [True, 720, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True]]],
  ['regression: frost limit steps',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 30, 25], [700, 33, 29], [700, 36, 30], [700, 36, -5], [700, 10, -40], [700, 30, 55]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False]]],
  ['control: dehumidify band',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[760, 56, 80],
     [752, 53, 80],
     [745, 52, 80],
     [741, 51, 80],
     [741, 50, 80],
     [752, 52, 80],
     [749, 52, 80]]],
   [[True, 720, False],
    [True, 735, False],
    [True, 740, False],
    [False, 745, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: mild dry day',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[700, 40, 45], [700, 43, 45], [700, 46, 45], [700, 48, 45]]],
   [[False, 750, True], [False, 750, True], [False, 750, False], [False, 750, False]]],
  ['regression: cold snap',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 12, -60], [700, 14, -60], [700, 16, -60], [700, 20, 50], [700, 20, 49]]],
   [[False, 750, False], [False, 750, False], [False, 750, False], [False, 750, False], [False, 750, True]]],
  ['regression: scenario 1',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[738, 41, 24],
     [734, 38, 21],
     [725, 33, 9],
     [726, 34, -2],
     [733, 39, 7],
     [743, 36, 7],
     [740, 38, 7],
     [752, 32, 19],
     [742, 34, 11],
     [732, 32, 9]]],
   [[False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: scenario 2',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[762, 20, -5],
     [767, 18, -6],
     [764, 13, -16],
     [765, 11, -12],
     [758, 10, -15],
     [757, 16, -3],
     [761, 16, 7],
     [758, 10, 13],
     [765, 10, 16],
     [763, 13, 12],
     [775, 16, 9],
     [765, 18, 4],
     [755, 20, 3],
     [754, 25, -3]]],
   [[True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, False]]],
  ['control: scenario 3',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 45},
    [[741, 31, 49],
     [750, 36, 55],
     [739, 36, 59],
     [734, 34, 55],
     [728, 33, 56],
     [717, 35, 48],
     [715, 34, 60],
     [726, 38, 57],
     [726, 39, 57],
     [719, 34, 54],
     [726, 39, 57],
     [729, 41, 61],
     [732, 39, 66],
     [743, 40, 75]]],
   [[False, 750, True],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]]],
 [['regression: frost limit steps',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 30, 25], [700, 33, 29], [700, 36, 30], [700, 36, -5], [700, 10, -40], [700, 30, 55]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False]]],
  ['regression: mild dry day',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[700, 40, 45], [700, 43, 45], [700, 46, 45], [700, 48, 45]]],
   [[False, 750, True], [False, 750, True], [False, 750, False], [False, 750, False]]],
  ['regression: summer then winter',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[765, 52, 80],
     [762, 58, 80],
     [745, 58, 80],
     [738, 50, 80],
     [700, 25, 10],
     [700, 29, 10],
     [700, 36, 10],
     [700, 10, -15]]],
   [[True, 750, False],
    [True, 720, False],
    [True, 720, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True]]],
  ['control: dehumidify band',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[760, 56, 80],
     [752, 53, 80],
     [745, 52, 80],
     [741, 51, 80],
     [741, 50, 80],
     [752, 52, 80],
     [749, 52, 80]]],
   [[True, 720, False],
    [True, 735, False],
    [True, 740, False],
    [False, 745, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: cold snap',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 12, -60], [700, 14, -60], [700, 16, -60], [700, 20, 50], [700, 20, 49]]],
   [[False, 750, False], [False, 750, False], [False, 750, False], [False, 750, False], [False, 750, True]]],
  ['control: scenario 1',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[741, 58, -1],
     [736, 54, -9],
     [726, 56, 2],
     [715, 54, 0],
     [721, 55, 1],
     [732, 51, -1],
     [731, 51, -7],
     [727, 55, -12],
     [721, 57, -12]]],
   [[True, 720, False],
    [True, 730, False],
    [True, 720, False],
    [False, 730, False],
    [False, 725, False],
    [False, 745, False],
    [False, 745, False],
    [False, 725, False],
    [False, 720, False]]],
  ['control: scenario 2',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 40},
    [[749, 37, 58],
     [756, 33, 55],
     [768, 38, 65],
     [771, 41, 72],
     [780, 47, 71],
     [774, 50, 64],
     [770, 54, 73],
     [777, 59, 73],
     [786, 63, 85],
     [788, 59, 90],
     [790, 61, 90],
     [782, 58, 85],
     [790, 53, 80],
     [790, 48, 82]]],
   [[False, 750, False],
    [False, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 730, False],
    [True, 730, False],
    [True, 730, False],
    [True, 730, False],
    [True, 730, False],
    [True, 735, False],
    [True, 750, False]]],
  ['control: scenario 3',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 45},
    [[757, 59, 32],
     [758, 65, 22],
     [769, 68, 15],
     [759, 74, 20],
     [747, 72, 31],
     [739, 66, 32],
     [736, 70, 38],
     [744, 65, 29],
     [745, 62, 40],
     [753, 57, 46],
     [759, 61, 35],
     [749, 57, 29]]],
   [[True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False]]]],
 [['regression: mild dry day',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[700, 40, 45], [700, 43, 45], [700, 46, 45], [700, 48, 45]]],
   [[False, 750, True], [False, 750, True], [False, 750, False], [False, 750, False]]],
  ['regression: cold snap',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 12, -60], [700, 14, -60], [700, 16, -60], [700, 20, 50], [700, 20, 49]]],
   [[False, 750, False], [False, 750, False], [False, 750, False], [False, 750, False], [False, 750, True]]],
  ['regression: summer then winter',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[765, 52, 80],
     [762, 58, 80],
     [745, 58, 80],
     [738, 50, 80],
     [700, 25, 10],
     [700, 29, 10],
     [700, 36, 10],
     [700, 10, -15]]],
   [[True, 750, False],
    [True, 720, False],
    [True, 720, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True]]],
  ['control: dehumidify band',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[760, 56, 80],
     [752, 53, 80],
     [745, 52, 80],
     [741, 51, 80],
     [741, 50, 80],
     [752, 52, 80],
     [749, 52, 80]]],
   [[True, 720, False],
    [True, 735, False],
    [True, 740, False],
    [False, 745, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: frost limit steps',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 30, 25], [700, 33, 29], [700, 36, 30], [700, 36, -5], [700, 10, -40], [700, 30, 55]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False]]],
  ['regression: scenario 1',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 35},
    [[760, 30, 52],
     [750, 32, 60],
     [748, 28, 48],
     [744, 33, 44],
     [754, 37, 54],
     [748, 40, 55],
     [758, 39, 61],
     [760, 42, 61],
     [754, 36, 49],
     [742, 30, 44],
     [731, 32, 54],
     [739, 36, 48],
     [733, 36, 54]]],
   [[False, 750, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: scenario 2',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 45},
    [[746, 32, -7],
     [745, 28, -12],
     [741, 24, -18],
     [736, 26, -12],
     [729, 31, 0],
     [720, 32, 7],
     [730, 30, 14],
     [728, 28, 19],
     [725, 23, 17],
     [729, 20, 18],
     [717, 24, 19],
     [715, 19, 10],
     [723, 14, 20],
     [722, 10, 23]]],
   [[False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True]]],
  ['control: scenario 3',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 35},
    [[757, 58, 62],
     [767, 52, 71],
     [773, 56, 59],
     [776, 56, 64],
     [765, 59, 59],
     [759, 53, 53],
     [771, 51, 47],
     [775, 55, 38],
     [773, 53, 28],
     [777, 59, 17],
     [785, 57, 9],
     [777, 61, 4]]],
   [[True, 730, False],
    [True, 740, False],
    [True, 730, False],
    [True, 730, False],
    [True, 730, False],
    [True, 735, False],
    [True, 745, False],
    [True, 730, False],
    [True, 735, False],
    [True, 730, False],
    [True, 730, False],
    [True, 730, False]]]],
 [['regression: cold snap',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 12, -60], [700, 14, -60], [700, 16, -60], [700, 20, 50], [700, 20, 49]]],
   [[False, 750, False], [False, 750, False], [False, 750, False], [False, 750, False], [False, 750, True]]],
  ['regression: scenario 1',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[741, 41, 9],
     [745, 42, 4],
     [749, 41, 7],
     [737, 37, 8],
     [740, 34, 14],
     [733, 38, 20],
     [730, 44, 9],
     [724, 38, 16],
     [725, 32, 6],
     [721, 27, -4]]],
   [[False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: summer then winter',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[765, 52, 80],
     [762, 58, 80],
     [745, 58, 80],
     [738, 50, 80],
     [700, 25, 10],
     [700, 29, 10],
     [700, 36, 10],
     [700, 10, -15]]],
   [[True, 750, False],
    [True, 720, False],
    [True, 720, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True]]],
  ['control: dehumidify band',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[760, 56, 80],
     [752, 53, 80],
     [745, 52, 80],
     [741, 51, 80],
     [741, 50, 80],
     [752, 52, 80],
     [749, 52, 80]]],
   [[True, 720, False],
    [True, 735, False],
    [True, 740, False],
    [False, 745, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: frost limit steps',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 30, 25], [700, 33, 29], [700, 36, 30], [700, 36, -5], [700, 10, -40], [700, 30, 55]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False]]],
  ['regression: mild dry day',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[700, 40, 45], [700, 43, 45], [700, 46, 45], [700, 48, 45]]],
   [[False, 750, True], [False, 750, True], [False, 750, False], [False, 750, False]]],
  ['regression: scenario 2',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[755, 29, 22],
     [752, 27, 11],
     [752, 25, 3],
     [763, 20, -7],
     [756, 25, -6],
     [766, 23, -4],
     [768, 25, 5],
     [774, 26, 7],
     [781, 22, -4]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [True, 750, True],
    [True, 750, False],
    [True, 750, False],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True]]],
  ['regression: scenario 3',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[761, 42, -7],
     [772, 41, 1],
     [768, 39, 5],
     [769, 39, -1],
     [759, 38, 1],
     [759, 43, -3],
     [764, 37, -15],
     [772, 40, -24],
     [779, 41, -30],
     [778, 45, -30],
     [772, 46, -30],
     [780, 40, -29],
     [771, 43, -30],
     [780, 40, -27]]],
   [[True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False]]]],
 [['regression: scenario 3',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[758, 47, 40],
     [762, 48, 47],
     [771, 44, 41],
     [782, 45, 36],
     [790, 48, 36],
     [787, 45, 25],
     [790, 40, 20],
     [790, 38, 12],
     [790, 35, 17],
     [787, 40, 13],
     [780, 36, 2],
     [774, 40, 1],
     [786, 44, 1],
     [778, 39, 11]]],
   [[False, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False]]],
  ['regression: scenario 1',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 35},
    [[755, 53, 26],
     [756, 54, 25],
     [766, 54, 30],
     [774, 48, 25],
     [783, 43, 35],
     [778, 37, 35],
     [777, 33, 39],
     [784, 35, 49],
     [779, 31, 39],
     [788, 27, 45],
     [778, 31, 42],
     [779, 31, 44],
     [789, 36, 51]]],
   [[False, 750, False],
    [False, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, False]]],
  ['regression: summer then winter',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[765, 52, 80],
     [762, 58, 80],
     [745, 58, 80],
     [738, 50, 80],
     [700, 25, 10],
     [700, 29, 10],
     [700, 36, 10],
     [700, 10, -15]]],
   [[True, 750, False],
    [True, 720, False],
    [True, 720, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True]]],
  ['control: dehumidify band',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[760, 56, 80],
     [752, 53, 80],
     [745, 52, 80],
     [741, 51, 80],
     [741, 50, 80],
     [752, 52, 80],
     [749, 52, 80]]],
   [[True, 720, False],
    [True, 735, False],
    [True, 740, False],
    [False, 745, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: frost limit steps',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 30, 25], [700, 33, 29], [700, 36, 30], [700, 36, -5], [700, 10, -40], [700, 30, 55]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False]]],
  ['regression: mild dry day',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[700, 40, 45], [700, 43, 45], [700, 46, 45], [700, 48, 45]]],
   [[False, 750, True], [False, 750, True], [False, 750, False], [False, 750, False]]],
  ['regression: cold snap',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 12, -60], [700, 14, -60], [700, 16, -60], [700, 20, 50], [700, 20, 49]]],
   [[False, 750, False], [False, 750, False], [False, 750, False], [False, 750, False], [False, 750, True]]],
  ['control: scenario 2',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 45},
    [[759, 30, 36],
     [770, 33, 36],
     [759, 34, 36],
     [752, 33, 36],
     [754, 27, 25],
     [764, 25, 15],
     [772, 25, 26],
     [784, 19, 22],
     [790, 21, 21]]],
   [[False, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

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

N = 1
observations = []
def solve(settings, samples):
    dehum = False
    cooling = False
    humid = False
    out = []
    for temp, rh, outdoor in samples:
        if dehum and rh <= settings['rh_sp']:
            dehum = False
        elif not dehum and rh > settings['rh_sp'] + 5:
            dehum = True
        eff = settings['cool_sp']
        if dehum:
            eff -= min(settings['max_overcool'], (rh - settings['rh_sp']) * 5)
        if cooling and temp <= eff:
            cooling = False
        elif not cooling and temp > eff + 10:
            cooling = True
        allowed = max(15, min(45, 40 + (outdoor - 20) // 10 * 5))
        target = max(settings['hum_sp'], allowed)
        if outdoor >= 50:
            humid = False
        elif humid and rh >= target:
            humid = False
        elif not humid and rh < target - 3:
            humid = True
        out.append([cooling, eff, humid])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: summer then winter',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[765, 52, 80],
     [762, 58, 80],
     [745, 58, 80],
     [738, 50, 80],
     [700, 25, 10],
     [700, 29, 10],
     [700, 36, 10],
     [700, 10, -15]]],
   [[True, 750, False],
    [True, 720, False],
    [True, 720, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True]]],
  ['regression: frost limit steps',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 30, 25], [700, 33, 29], [700, 36, 30], [700, 36, -5], [700, 10, -40], [700, 30, 55]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False]]],
  ['control: dehumidify band',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[760, 56, 80],
     [752, 53, 80],
     [745, 52, 80],
     [741, 51, 80],
     [741, 50, 80],
     [752, 52, 80],
     [749, 52, 80]]],
   [[True, 720, False],
    [True, 735, False],
    [True, 740, False],
    [False, 745, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: mild dry day',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[700, 40, 45], [700, 43, 45], [700, 46, 45], [700, 48, 45]]],
   [[False, 750, True], [False, 750, True], [False, 750, False], [False, 750, False]]],
  ['regression: cold snap',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 12, -60], [700, 14, -60], [700, 16, -60], [700, 20, 50], [700, 20, 49]]],
   [[False, 750, False], [False, 750, False], [False, 750, False], [False, 750, False], [False, 750, True]]],
  ['regression: scenario 1',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[738, 41, 24],
     [734, 38, 21],
     [725, 33, 9],
     [726, 34, -2],
     [733, 39, 7],
     [743, 36, 7],
     [740, 38, 7],
     [752, 32, 19],
     [742, 34, 11],
     [732, 32, 9]]],
   [[False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: scenario 2',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[762, 20, -5],
     [767, 18, -6],
     [764, 13, -16],
     [765, 11, -12],
     [758, 10, -15],
     [757, 16, -3],
     [761, 16, 7],
     [758, 10, 13],
     [765, 10, 16],
     [763, 13, 12],
     [775, 16, 9],
     [765, 18, 4],
     [755, 20, 3],
     [754, 25, -3]]],
   [[True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, False]]],
  ['control: scenario 3',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 45},
    [[741, 31, 49],
     [750, 36, 55],
     [739, 36, 59],
     [734, 34, 55],
     [728, 33, 56],
     [717, 35, 48],
     [715, 34, 60],
     [726, 38, 57],
     [726, 39, 57],
     [719, 34, 54],
     [726, 39, 57],
     [729, 41, 61],
     [732, 39, 66],
     [743, 40, 75]]],
   [[False, 750, True],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]]],
 [['regression: frost limit steps',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 30, 25], [700, 33, 29], [700, 36, 30], [700, 36, -5], [700, 10, -40], [700, 30, 55]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False]]],
  ['regression: mild dry day',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[700, 40, 45], [700, 43, 45], [700, 46, 45], [700, 48, 45]]],
   [[False, 750, True], [False, 750, True], [False, 750, False], [False, 750, False]]],
  ['regression: summer then winter',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[765, 52, 80],
     [762, 58, 80],
     [745, 58, 80],
     [738, 50, 80],
     [700, 25, 10],
     [700, 29, 10],
     [700, 36, 10],
     [700, 10, -15]]],
   [[True, 750, False],
    [True, 720, False],
    [True, 720, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True]]],
  ['control: dehumidify band',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[760, 56, 80],
     [752, 53, 80],
     [745, 52, 80],
     [741, 51, 80],
     [741, 50, 80],
     [752, 52, 80],
     [749, 52, 80]]],
   [[True, 720, False],
    [True, 735, False],
    [True, 740, False],
    [False, 745, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: cold snap',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 12, -60], [700, 14, -60], [700, 16, -60], [700, 20, 50], [700, 20, 49]]],
   [[False, 750, False], [False, 750, False], [False, 750, False], [False, 750, False], [False, 750, True]]],
  ['control: scenario 1',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[741, 58, -1],
     [736, 54, -9],
     [726, 56, 2],
     [715, 54, 0],
     [721, 55, 1],
     [732, 51, -1],
     [731, 51, -7],
     [727, 55, -12],
     [721, 57, -12]]],
   [[True, 720, False],
    [True, 730, False],
    [True, 720, False],
    [False, 730, False],
    [False, 725, False],
    [False, 745, False],
    [False, 745, False],
    [False, 725, False],
    [False, 720, False]]],
  ['control: scenario 2',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 40},
    [[749, 37, 58],
     [756, 33, 55],
     [768, 38, 65],
     [771, 41, 72],
     [780, 47, 71],
     [774, 50, 64],
     [770, 54, 73],
     [777, 59, 73],
     [786, 63, 85],
     [788, 59, 90],
     [790, 61, 90],
     [782, 58, 85],
     [790, 53, 80],
     [790, 48, 82]]],
   [[False, 750, False],
    [False, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 730, False],
    [True, 730, False],
    [True, 730, False],
    [True, 730, False],
    [True, 730, False],
    [True, 735, False],
    [True, 750, False]]],
  ['control: scenario 3',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 45},
    [[757, 59, 32],
     [758, 65, 22],
     [769, 68, 15],
     [759, 74, 20],
     [747, 72, 31],
     [739, 66, 32],
     [736, 70, 38],
     [744, 65, 29],
     [745, 62, 40],
     [753, 57, 46],
     [759, 61, 35],
     [749, 57, 29]]],
   [[True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False],
    [True, 720, False]]]],
 [['regression: mild dry day',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[700, 40, 45], [700, 43, 45], [700, 46, 45], [700, 48, 45]]],
   [[False, 750, True], [False, 750, True], [False, 750, False], [False, 750, False]]],
  ['regression: cold snap',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 12, -60], [700, 14, -60], [700, 16, -60], [700, 20, 50], [700, 20, 49]]],
   [[False, 750, False], [False, 750, False], [False, 750, False], [False, 750, False], [False, 750, True]]],
  ['regression: summer then winter',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[765, 52, 80],
     [762, 58, 80],
     [745, 58, 80],
     [738, 50, 80],
     [700, 25, 10],
     [700, 29, 10],
     [700, 36, 10],
     [700, 10, -15]]],
   [[True, 750, False],
    [True, 720, False],
    [True, 720, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True]]],
  ['control: dehumidify band',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[760, 56, 80],
     [752, 53, 80],
     [745, 52, 80],
     [741, 51, 80],
     [741, 50, 80],
     [752, 52, 80],
     [749, 52, 80]]],
   [[True, 720, False],
    [True, 735, False],
    [True, 740, False],
    [False, 745, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: frost limit steps',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 30, 25], [700, 33, 29], [700, 36, 30], [700, 36, -5], [700, 10, -40], [700, 30, 55]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False]]],
  ['regression: scenario 1',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 35},
    [[760, 30, 52],
     [750, 32, 60],
     [748, 28, 48],
     [744, 33, 44],
     [754, 37, 54],
     [748, 40, 55],
     [758, 39, 61],
     [760, 42, 61],
     [754, 36, 49],
     [742, 30, 44],
     [731, 32, 54],
     [739, 36, 48],
     [733, 36, 54]]],
   [[False, 750, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: scenario 2',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 45},
    [[746, 32, -7],
     [745, 28, -12],
     [741, 24, -18],
     [736, 26, -12],
     [729, 31, 0],
     [720, 32, 7],
     [730, 30, 14],
     [728, 28, 19],
     [725, 23, 17],
     [729, 20, 18],
     [717, 24, 19],
     [715, 19, 10],
     [723, 14, 20],
     [722, 10, 23]]],
   [[False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, True]]],
  ['control: scenario 3',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 35},
    [[757, 58, 62],
     [767, 52, 71],
     [773, 56, 59],
     [776, 56, 64],
     [765, 59, 59],
     [759, 53, 53],
     [771, 51, 47],
     [775, 55, 38],
     [773, 53, 28],
     [777, 59, 17],
     [785, 57, 9],
     [777, 61, 4]]],
   [[True, 730, False],
    [True, 740, False],
    [True, 730, False],
    [True, 730, False],
    [True, 730, False],
    [True, 735, False],
    [True, 745, False],
    [True, 730, False],
    [True, 735, False],
    [True, 730, False],
    [True, 730, False],
    [True, 730, False]]]],
 [['regression: cold snap',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 12, -60], [700, 14, -60], [700, 16, -60], [700, 20, 50], [700, 20, 49]]],
   [[False, 750, False], [False, 750, False], [False, 750, False], [False, 750, False], [False, 750, True]]],
  ['regression: scenario 1',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[741, 41, 9],
     [745, 42, 4],
     [749, 41, 7],
     [737, 37, 8],
     [740, 34, 14],
     [733, 38, 20],
     [730, 44, 9],
     [724, 38, 16],
     [725, 32, 6],
     [721, 27, -4]]],
   [[False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: summer then winter',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[765, 52, 80],
     [762, 58, 80],
     [745, 58, 80],
     [738, 50, 80],
     [700, 25, 10],
     [700, 29, 10],
     [700, 36, 10],
     [700, 10, -15]]],
   [[True, 750, False],
    [True, 720, False],
    [True, 720, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True]]],
  ['control: dehumidify band',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[760, 56, 80],
     [752, 53, 80],
     [745, 52, 80],
     [741, 51, 80],
     [741, 50, 80],
     [752, 52, 80],
     [749, 52, 80]]],
   [[True, 720, False],
    [True, 735, False],
    [True, 740, False],
    [False, 745, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: frost limit steps',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 30, 25], [700, 33, 29], [700, 36, 30], [700, 36, -5], [700, 10, -40], [700, 30, 55]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False]]],
  ['regression: mild dry day',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[700, 40, 45], [700, 43, 45], [700, 46, 45], [700, 48, 45]]],
   [[False, 750, True], [False, 750, True], [False, 750, False], [False, 750, False]]],
  ['regression: scenario 2',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[755, 29, 22],
     [752, 27, 11],
     [752, 25, 3],
     [763, 20, -7],
     [756, 25, -6],
     [766, 23, -4],
     [768, 25, 5],
     [774, 26, 7],
     [781, 22, -4]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [True, 750, True],
    [True, 750, False],
    [True, 750, False],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True]]],
  ['regression: scenario 3',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[761, 42, -7],
     [772, 41, 1],
     [768, 39, 5],
     [769, 39, -1],
     [759, 38, 1],
     [759, 43, -3],
     [764, 37, -15],
     [772, 40, -24],
     [779, 41, -30],
     [778, 45, -30],
     [772, 46, -30],
     [780, 40, -29],
     [771, 43, -30],
     [780, 40, -27]]],
   [[True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False]]]],
 [['regression: scenario 3',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[758, 47, 40],
     [762, 48, 47],
     [771, 44, 41],
     [782, 45, 36],
     [790, 48, 36],
     [787, 45, 25],
     [790, 40, 20],
     [790, 38, 12],
     [790, 35, 17],
     [787, 40, 13],
     [780, 36, 2],
     [774, 40, 1],
     [786, 44, 1],
     [778, 39, 11]]],
   [[False, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False]]],
  ['regression: scenario 1',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 35},
    [[755, 53, 26],
     [756, 54, 25],
     [766, 54, 30],
     [774, 48, 25],
     [783, 43, 35],
     [778, 37, 35],
     [777, 33, 39],
     [784, 35, 49],
     [779, 31, 39],
     [788, 27, 45],
     [778, 31, 42],
     [779, 31, 44],
     [789, 36, 51]]],
   [[False, 750, False],
    [False, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, False],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, False]]],
  ['regression: summer then winter',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[765, 52, 80],
     [762, 58, 80],
     [745, 58, 80],
     [738, 50, 80],
     [700, 25, 10],
     [700, 29, 10],
     [700, 36, 10],
     [700, 10, -15]]],
   [[True, 750, False],
    [True, 720, False],
    [True, 720, False],
    [False, 750, False],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True]]],
  ['control: dehumidify band',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 40},
    [[760, 56, 80],
     [752, 53, 80],
     [745, 52, 80],
     [741, 51, 80],
     [741, 50, 80],
     [752, 52, 80],
     [749, 52, 80]]],
   [[True, 720, False],
    [True, 735, False],
    [True, 740, False],
    [False, 745, False],
    [False, 750, False],
    [False, 750, False],
    [False, 750, False]]],
  ['regression: frost limit steps',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 30, 25], [700, 33, 29], [700, 36, 30], [700, 36, -5], [700, 10, -40], [700, 30, 55]]],
   [[False, 750, True],
    [False, 750, True],
    [False, 750, True],
    [False, 750, False],
    [False, 750, True],
    [False, 750, False]]],
  ['regression: mild dry day',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 50},
    [[700, 40, 45], [700, 43, 45], [700, 46, 45], [700, 48, 45]]],
   [[False, 750, True], [False, 750, True], [False, 750, False], [False, 750, False]]],
  ['regression: cold snap',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 20, 'hum_sp': 45},
    [[700, 12, -60], [700, 14, -60], [700, 16, -60], [700, 20, 50], [700, 20, 49]]],
   [[False, 750, False], [False, 750, False], [False, 750, False], [False, 750, False], [False, 750, True]]],
  ['control: scenario 2',
   [{'cool_sp': 750, 'rh_sp': 50, 'max_overcool': 30, 'hum_sp': 45},
    [[759, 30, 36],
     [770, 33, 36],
     [759, 34, 36],
     [752, 33, 36],
     [754, 27, 25],
     [764, 25, 15],
     [772, 25, 26],
     [784, 19, 22],
     [790, 21, 21]]],
   [[False, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True],
    [True, 750, True]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Windows sweat and frost on cold days because the humidifier chases the user setpoint.

Thermostat humidity functions per sample; samples are [temp tenths F, indoor RH %, outdoor whole F]. Dehumidify-by-overcooling turns on when RH > rh_sp + 5 and off when RH <= rh_sp; while on, the effective cooling setpoint is lowered by min(max_overcool, (RH - rh_sp) * 5) tenths. Cooling starts above effective + 1.0 F and ends at <= effective. Humidifier: allowed RH = 40 + floor((outdoor - 20) / 10) * 5 clamped to 15..45; target = min(hum_sp, allowed); it is off when outdoor >= 50, otherwise starts below target - 3 and stops at >= target. Return [cooling, effective_sp, humidifier].

split: open-access


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

N = 1
observations = []
def solve(samples):
    last = None
    out = []
    for readings in samples:
        valid = [(t, occ) for room, t, occ in readings if t is not None]
        pool = [t for t, occ in valid if occ] or [t for t, occ in valid]
        if pool:
            last = (2 * sum(pool) + len(pool)) // (2 * len(pool))
        out.append(last)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: occupancy and faults',
   [[[['liv', 700, True], ['bed', 680, False]],
     [['liv', None, True], ['bed', 681, False], ['den', 690, False]],
     [['liv', 1200, True]],
     [['liv', 701, True], ['bed', 702, True]]]],
   [700, 686, 686, 702]],
  ['regression: shorted sensor',
   [[[['a', 700, True], ['b', 5, True]], [['a', 1300, False], ['b', 690, False]]]],
   [700, 690]],
  ['control: first sample all invalid',
   [[[['a', None, True]], [['a', 700, True]], [['a', None, False]]]],
   [None, 700, 700]],
  ['control: single occupied room',
   [[[['a', 700, True], ['b', 650, False], ['c', 660, False]], [['a', 707, True], ['b', 704, True]]]],
   [700, 706]],
  ['control: scenario 1',
   [[[['living', 611, False], ['bed', 799, True]],
     [['living', 697, True]],
     [['living', 697, False], ['bed', 609, True]],
     [['living', 751, False], ['bed', 736, True], ['den', 616, True]],
     [['living', 1100, False], ['bed', 686, True]],
     [['living', 798, False], ['bed', 743, True], ['den', 646, False], ['office', 720, False]],
     [['living', 668, False], ['bed', None, True], ['den', None, True], ['office', 795, False]]]],
   [799, 697, 609, 676, 686, 743, 732]],
  ['regression: scenario 2',
   [[[['living', 602, False], ['bed', 665, False], ['den', 790, False], ['office', 677, False]],
     [['living', 638, False]],
     [['living', 602, False], ['bed', 750, True]],
     [['living', None, True], ['bed', 250, False], ['den', 250, True]],
     [['living', 744, True], ['bed', 711, True], ['den', 676, False], ['office', 640, True]],
     [['living', 771, False], ['bed', 646, True]],
     [['living', 608, False]],
     [['living', 663, True], ['bed', 793, True], ['den', 250, True], ['office', 743, False]]]],
   [684, 638, 750, 750, 698, 646, 608, 728]],
  ['regression: scenario 3',
   [[[['living', 677, True]],
     [['living', 624, True], ['bed', 620, True]],
     [['living', 605, True], ['bed', 250, False]],
     [['living', 764, False]],
     [['living', 612, False], ['bed', None, True], ['den', 664, True]],
     [['living', None, True], ['bed', 250, False], ['den', 250, True]],
     [['living', 745, True], ['bed', None, False]],
     [['living', 665, True]]]],
   [677, 622, 605, 764, 664, 664, 745, 665]],
  ['regression: scenario 4',
   [[[['living', 600, True]],
     [['living', 742, True], ['bed', 607, False], ['den', 638, True], ['office', 791, True]],
     [['living', 710, False], ['bed', 602, True], ['den', 716, False]],
     [['living', 607, False], ['bed', 735, True], ['den', 739, False], ['office', 723, True]],
     [['living', 621, True], ['bed', 625, False], ['den', 688, True], ['office', 627, False]],
     [['living', 677, False], ['bed', 775, True]],
     [['living', 1100, False], ['bed', None, False], ['den', 687, False]]]],
   [600, 724, 602, 729, 655, 775, 687]]],
 [['regression: shorted sensor',
   [[[['a', 700, True], ['b', 5, True]], [['a', 1300, False], ['b', 690, False]]]],
   [700, 690]],
  ['regression: scenario 4',
   [[[['living', 713, False]],
     [['living', 741, True], ['bed', 652, False], ['den', 796, False], ['office', 784, False]],
     [['living', 756, True], ['bed', 687, True], ['den', 250, False], ['office', 657, False]],
     [['living', 601, True], ['bed', 743, True], ['den', 250, True]],
     [['living', 728, False]],
     [['living', 605, False], ['bed', 766, True], ['den', 601, False]],
     [['living', 748, True]],
     [['living', 1100, True], ['bed', 622, False], ['den', 714, True], ['office', 644, True]],
     [['living', 773, True]]]],
   [713, 741, 722, 672, 728, 766, 748, 679, 773]],
  ['regression: occupancy and faults',
   [[[['liv', 700, True], ['bed', 680, False]],
     [['liv', None, True], ['bed', 681, False], ['den', 690, False]],
     [['liv', 1200, True]],
     [['liv', 701, True], ['bed', 702, True]]]],
   [700, 686, 686, 702]],
  ['control: first sample all invalid',
   [[[['a', None, True]], [['a', 700, True]], [['a', None, False]]]],
   [None, 700, 700]],
  ['control: single occupied room',
   [[[['a', 700, True], ['b', 650, False], ['c', 660, False]], [['a', 707, True], ['b', 704, True]]]],
   [700, 706]],
  ['control: scenario 1',
   [[[['living', 631, False], ['bed', None, True]],
     [['living', 674, True], ['bed', 788, True]],
     [['living', 629, False]],
     [['living', 617, False], ['bed', 636, True], ['den', 622, True]],
     [['living', 602, True], ['bed', 659, True], ['den', 604, False]],
     [['living', 641, True], ['bed', 600, True]],
     [['living', 781, True]],
     [['living', 615, True], ['bed', 788, True], ['den', 658, True]]]],
   [631, 731, 629, 629, 631, 621, 781, 687]],
  ['control: scenario 2',
   [[[['living', 675, True], ['bed', 724, False], ['den', 793, True]],
     [['living', 711, False], ['bed', 720, False]],
     [['living', 722, False], ['bed', 1100, False], ['den', 606, False], ['office', 625, True]],
     [['living', 657, False], ['bed', 619, True], ['den', 800, True], ['office', 629, True]],
     [['living', 765, True], ['bed', 726, True]],
     [['living', 785, False], ['bed', 626, False]]]],
   [734, 716, 625, 683, 746, 706]],
  ['regression: scenario 3',
   [[[['living', 795, False]],
     [['living', 769, False], ['bed', 675, False]],
     [['living', 640, False]],
     [['living', None, False]],
     [['living', None, False], ['bed', 790, True], ['den', 684, False], ['office', 789, True]],
     [['living', 722, True], ['bed', 750, True], ['den', 250, True]],
     [['living', 663, True], ['bed', 670, True]],
     [['living', 628, False], ['bed', 687, False], ['den', 635, False]]]],
   [795, 722, 640, 640, 790, 736, 667, 650]]],
 [['regression: scenario 1',
   [[[['living', 627, False], ['bed', 693, True], ['den', 769, True], ['office', 704, True]],
     [['living', 738, True], ['bed', 638, True]],
     [['living', 760, True], ['bed', 696, True], ['den', 683, False]],
     [['living', 771, False], ['bed', 1100, False]],
     [['living', 686, True]],
     [['living', 734, True]],
     [['living', None, True], ['bed', 649, False], ['den', 767, False]],
     [['living', 722, True]],
     [['living', 686, True], ['bed', 715, False], ['den', 617, False], ['office', 250, False]],
     [['living', 790, True]]]],
   [722, 688, 728, 771, 686, 734, 708, 722, 686, 790]],
  ['regression: scenario 2',
   [[[['living', 663, False], ['bed', 781, True], ['den', 775, False], ['office', 722, True]],
     [['living', 655, False]],
     [['living', 777, False], ['bed', 790, True], ['den', 637, False], ['office', 682, False]],
     [['living', 250, False], ['bed', 701, True], ['den', 745, True], ['office', 626, False]],
     [['living', 619, False]],
     [['living', 619, True], ['bed', 710, True]],
     [['living', 732, False]],
     [['living', 772, False]],
     [['living', None, True], ['bed', 664, True], ['den', 728, True], ['office', 783, False]],
     [['living', 1100, True], ['bed', 734, True], ['den', 657, False], ['office', 601, False]]]],
   [752, 655, 790, 723, 619, 665, 732, 772, 696, 734]],
  ['regression: occupancy and faults',
   [[[['liv', 700, True], ['bed', 680, False]],
     [['liv', None, True], ['bed', 681, False], ['den', 690, False]],
     [['liv', 1200, True]],
     [['liv', 701, True], ['bed', 702, True]]]],
   [700, 686, 686, 702]],
  ['regression: shorted sensor',
   [[[['a', 700, True], ['b', 5, True]], [['a', 1300, False], ['b', 690, False]]]],
   [700, 690]],
  ['control: first sample all invalid',
   [[[['a', None, True]], [['a', 700, True]], [['a', None, False]]]],
   [None, 700, 700]],
  ['control: single occupied room',
   [[[['a', 700, True], ['b', 650, False], ['c', 660, False]], [['a', 707, True], ['b', 704, True]]]],
   [700, 706]],
  ['regression: scenario 3',
   [[[['living', 740, True], ['bed', None, False], ['den', 718, True], ['office', 628, True]],
     [['living', 687, True]],
     [['living', 766, True], ['bed', 604, False], ['den', 725, False], ['office', 735, False]],
     [['living', 788, False], ['bed', 698, False], ['den', 700, False], ['office', None, True]],
     [['living', None, False], ['bed', 607, True], ['den', 754, False]],
     [['living', 250, False], ['bed', 649, True], ['den', 666, False]],
     [['living', None, True], ['bed', 785, True]],
     [['living', 715, True], ['bed', 699, False], ['den', 1100, True]],
     [['living', 605, False], ['bed', 735, False]]]],
   [695, 687, 766, 729, 607, 649, 785, 715, 670]],
  ['regression: scenario 4',
   [[[['living', 647, True], ['bed', 693, False]],
     [['living', None, False], ['bed', 1100, False], ['den', None, True], ['office', None, False]],
     [['living', 791, False], ['bed', 250, False], ['den', 778, True]],
     [['living', 650, False], ['bed', None, True]],
     [['living', 1100, True], ['bed', 680, False], ['den', 250, False]],
     [['living', 700, True], ['bed', 1100, True], ['den', 712, False]],
     [['living', 662, True], ['bed', 670, True]]]],
   [647, 647, 778, 650, 680, 700, 666]]],
 [['regression: scenario 4',
   [[[['living', 614, False]],
     [['living', 616, True], ['bed', None, True], ['den', 783, True]],
     [['living', 250, True], ['bed', 250, True]],
     [['living', None, True]],
     [['living', 663, True]],
     [['living', 656, True], ['bed', 250, True], ['den', 679, True]],
     [['living', 799, True], ['bed', 707, True], ['den', 751, True]],
     [['living', None, True]]]],
   [614, 700, 700, 700, 663, 668, 752, 752]],
  ['regression: scenario 7',
   [[[['living', 776, True], ['bed', 1100, False], ['den', 734, False]],
     [['living', 250, True], ['bed', 734, False], ['den', 775, True], ['office', 1100, False]],
     [['living', 250, False], ['bed', 747, True], ['den', None, True]],
     [['living', 622, True], ['bed', 623, False], ['den', 793, True]],
     [['living', 728, True], ['bed', 708, True], ['den', None, False]],
     [['living', 644, False]],
     [['living', 765, True], ['bed', 650, True], ['den', 749, False], ['office', 1100, False]],
     [['living', 672, False], ['bed', 769, True], ['den', 1100, True]],
     [['living', 729, True], ['bed', None, False]],
     [['living', 794, False], ['bed', 670, True]]]],
   [776, 775, 747, 708, 718, 644, 708, 769, 729, 670]],
  ['regression: occupancy and faults',
   [[[['liv', 700, True], ['bed', 680, False]],
     [['liv', None, True], ['bed', 681, False], ['den', 690, False]],
     [['liv', 1200, True]],
     [['liv', 701, True], ['bed', 702, True]]]],
   [700, 686, 686, 702]],
  ['regression: shorted sensor',
   [[[['a', 700, True], ['b', 5, True]], [['a', 1300, False], ['b', 690, False]]]],
   [700, 690]],
  ['control: first sample all invalid',
   [[[['a', None, True]], [['a', 700, True]], [['a', None, False]]]],
   [None, 700, 700]],
  ['control: single occupied room',
   [[[['a', 700, True], ['b', 650, False], ['c', 660, False]], [['a', 707, True], ['b', 704, True]]]],
   [700, 706]],
  ['control: scenario 1',
   [[[['living', 782, False], ['bed', 708, True], ['den', 678, True]],
     [['living', 772, False], ['bed', 795, True]],
     [['living', 744, True], ['bed', 616, True], ['den', 694, True]],
     [['living', 790, False], ['bed', 733, True]],
     [['living', 722, True], ['bed', 701, False]],
     [['living', 699, False], ['bed', 636, False]]]],
   [693, 795, 685, 733, 722, 668]],
  ['regression: scenario 2',
   [[[['living', 675, False], ['bed', 659, True], ['den', 738, False], ['office', 1100, False]],
     [['living', 250, True], ['bed', 649, True]],
     [['living', 604, True]],
     [['living', 629, True], ['bed', None, True], ['den', 610, True]],
     [['living', 633, False], ['bed', None, True], ['den', 778, True], ['office', 795, False]],
     [['living', None, False]]]],
   [659, 649, 604, 620, 778, 778]]],
 [['regression: scenario 3',
   [[[['living', None, True], ['bed', 631, True]],
     [['living', 654, False], ['bed', 779, False], ['den', 716, True]],
     [['living', 799, True]],
     [['living', 664, True]],
     [['living', 622, False]],
     [['living', 697, False], ['bed', 685, False]],
     [['living', 727, False], ['bed', 250, True], ['den', 737, False], ['office', 692, False]]]],
   [631, 716, 799, 664, 622, 691, 719]],
  ['regression: scenario 6',
   [[[['living', 696, False], ['bed', 633, True]],
     [['living', 662, False], ['bed', 1100, False]],
     [['living', 654, True]],
     [['living', 773, True], ['bed', 789, False], ['den', 791, True], ['office', 696, True]],
     [['living', 709, True], ['bed', 753, False]]]],
   [633, 662, 654, 753, 709]],
  ['regression: occupancy and faults',
   [[[['liv', 700, True], ['bed', 680, False]],
     [['liv', None, True], ['bed', 681, False], ['den', 690, False]],
     [['liv', 1200, True]],
     [['liv', 701, True], ['bed', 702, True]]]],
   [700, 686, 686, 702]],
  ['regression: shorted sensor',
   [[[['a', 700, True], ['b', 5, True]], [['a', 1300, False], ['b', 690, False]]]],
   [700, 690]],
  ['control: first sample all invalid',
   [[[['a', None, True]], [['a', 700, True]], [['a', None, False]]]],
   [None, 700, 700]],
  ['control: single occupied room',
   [[[['a', 700, True], ['b', 650, False], ['c', 660, False]], [['a', 707, True], ['b', 704, True]]]],
   [700, 706]],
  ['regression: scenario 1',
   [[[['living', 1100, True]],
     [['living', 634, False], ['bed', 740, False], ['den', None, True]],
     [['living', 1100, True]],
     [['living', 618, False], ['bed', 787, False], ['den', 754, False]],
     [['living', 673, False], ['bed', 795, True], ['den', 612, False], ['office', 721, True]]]],
   [None, 687, 687, 720, 758]],
  ['regression: scenario 2',
   [[[['living', 733, True], ['bed', 629, True], ['den', 631, True], ['office', 649, True]],
     [['living', 766, True]],
     [['living', 727, False], ['bed', 610, False]],
     [['living', None, True]],
     [['living', 627, False]],
     [['living', 689, True], ['bed', 635, True], ['den', 250, False]],
     [['living', 613, False], ['bed', 717, False]],
     [['living', 1100, True]]]],
   [661, 766, 669, 669, 627, 662, 665, 665]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

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

N = 1
observations = []
def solve(samples):
    last = None
    out = []
    for readings in samples:
        valid = [(t, occ) for room, t, occ in readings if t is not None and t >= 320]
        pool = [t for t, occ in valid if occ] or [t for t, occ in valid]
        if pool:
            last = (2 * sum(pool) + len(pool)) // (2 * len(pool))
        out.append(last)
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: occupancy and faults',
   [[[['liv', 700, True], ['bed', 680, False]],
     [['liv', None, True], ['bed', 681, False], ['den', 690, False]],
     [['liv', 1200, True]],
     [['liv', 701, True], ['bed', 702, True]]]],
   [700, 686, 686, 702]],
  ['regression: shorted sensor',
   [[[['a', 700, True], ['b', 5, True]], [['a', 1300, False], ['b', 690, False]]]],
   [700, 690]],
  ['control: first sample all invalid',
   [[[['a', None, True]], [['a', 700, True]], [['a', None, False]]]],
   [None, 700, 700]],
  ['control: single occupied room',
   [[[['a', 700, True], ['b', 650, False], ['c', 660, False]], [['a', 707, True], ['b', 704, True]]]],
   [700, 706]],
  ['control: scenario 1',
   [[[['living', 611, False], ['bed', 799, True]],
     [['living', 697, True]],
     [['living', 697, False], ['bed', 609, True]],
     [['living', 751, False], ['bed', 736, True], ['den', 616, True]],
     [['living', 1100, False], ['bed', 686, True]],
     [['living', 798, False], ['bed', 743, True], ['den', 646, False], ['office', 720, False]],
     [['living', 668, False], ['bed', None, True], ['den', None, True], ['office', 795, False]]]],
   [799, 697, 609, 676, 686, 743, 732]],
  ['regression: scenario 2',
   [[[['living', 602, False], ['bed', 665, False], ['den', 790, False], ['office', 677, False]],
     [['living', 638, False]],
     [['living', 602, False], ['bed', 750, True]],
     [['living', None, True], ['bed', 250, False], ['den', 250, True]],
     [['living', 744, True], ['bed', 711, True], ['den', 676, False], ['office', 640, True]],
     [['living', 771, False], ['bed', 646, True]],
     [['living', 608, False]],
     [['living', 663, True], ['bed', 793, True], ['den', 250, True], ['office', 743, False]]]],
   [684, 638, 750, 750, 698, 646, 608, 728]],
  ['regression: scenario 3',
   [[[['living', 677, True]],
     [['living', 624, True], ['bed', 620, True]],
     [['living', 605, True], ['bed', 250, False]],
     [['living', 764, False]],
     [['living', 612, False], ['bed', None, True], ['den', 664, True]],
     [['living', None, True], ['bed', 250, False], ['den', 250, True]],
     [['living', 745, True], ['bed', None, False]],
     [['living', 665, True]]]],
   [677, 622, 605, 764, 664, 664, 745, 665]],
  ['regression: scenario 4',
   [[[['living', 600, True]],
     [['living', 742, True], ['bed', 607, False], ['den', 638, True], ['office', 791, True]],
     [['living', 710, False], ['bed', 602, True], ['den', 716, False]],
     [['living', 607, False], ['bed', 735, True], ['den', 739, False], ['office', 723, True]],
     [['living', 621, True], ['bed', 625, False], ['den', 688, True], ['office', 627, False]],
     [['living', 677, False], ['bed', 775, True]],
     [['living', 1100, False], ['bed', None, False], ['den', 687, False]]]],
   [600, 724, 602, 729, 655, 775, 687]]],
 [['regression: shorted sensor',
   [[[['a', 700, True], ['b', 5, True]], [['a', 1300, False], ['b', 690, False]]]],
   [700, 690]],
  ['regression: scenario 4',
   [[[['living', 713, False]],
     [['living', 741, True], ['bed', 652, False], ['den', 796, False], ['office', 784, False]],
     [['living', 756, True], ['bed', 687, True], ['den', 250, False], ['office', 657, False]],
     [['living', 601, True], ['bed', 743, True], ['den', 250, True]],
     [['living', 728, False]],
     [['living', 605, False], ['bed', 766, True], ['den', 601, False]],
     [['living', 748, True]],
     [['living', 1100, True], ['bed', 622, False], ['den', 714, True], ['office', 644, True]],
     [['living', 773, True]]]],
   [713, 741, 722, 672, 728, 766, 748, 679, 773]],
  ['regression: occupancy and faults',
   [[[['liv', 700, True], ['bed', 680, False]],
     [['liv', None, True], ['bed', 681, False], ['den', 690, False]],
     [['liv', 1200, True]],
     [['liv', 701, True], ['bed', 702, True]]]],
   [700, 686, 686, 702]],
  ['control: first sample all invalid',
   [[[['a', None, True]], [['a', 700, True]], [['a', None, False]]]],
   [None, 700, 700]],
  ['control: single occupied room',
   [[[['a', 700, True], ['b', 650, False], ['c', 660, False]], [['a', 707, True], ['b', 704, True]]]],
   [700, 706]],
  ['control: scenario 1',
   [[[['living', 631, False], ['bed', None, True]],
     [['living', 674, True], ['bed', 788, True]],
     [['living', 629, False]],
     [['living', 617, False], ['bed', 636, True], ['den', 622, True]],
     [['living', 602, True], ['bed', 659, True], ['den', 604, False]],
     [['living', 641, True], ['bed', 600, True]],
     [['living', 781, True]],
     [['living', 615, True], ['bed', 788, True], ['den', 658, True]]]],
   [631, 731, 629, 629, 631, 621, 781, 687]],
  ['control: scenario 2',
   [[[['living', 675, True], ['bed', 724, False], ['den', 793, True]],
     [['living', 711, False], ['bed', 720, False]],
     [['living', 722, False], ['bed', 1100, False], ['den', 606, False], ['office', 625, True]],
     [['living', 657, False], ['bed', 619, True], ['den', 800, True], ['office', 629, True]],
     [['living', 765, True], ['bed', 726, True]],
     [['living', 785, False], ['bed', 626, False]]]],
   [734, 716, 625, 683, 746, 706]],
  ['regression: scenario 3',
   [[[['living', 795, False]],
     [['living', 769, False], ['bed', 675, False]],
     [['living', 640, False]],
     [['living', None, False]],
     [['living', None, False], ['bed', 790, True], ['den', 684, False], ['office', 789, True]],
     [['living', 722, True], ['bed', 750, True], ['den', 250, True]],
     [['living', 663, True], ['bed', 670, True]],
     [['living', 628, False], ['bed', 687, False], ['den', 635, False]]]],
   [795, 722, 640, 640, 790, 736, 667, 650]]],
 [['regression: scenario 1',
   [[[['living', 627, False], ['bed', 693, True], ['den', 769, True], ['office', 704, True]],
     [['living', 738, True], ['bed', 638, True]],
     [['living', 760, True], ['bed', 696, True], ['den', 683, False]],
     [['living', 771, False], ['bed', 1100, False]],
     [['living', 686, True]],
     [['living', 734, True]],
     [['living', None, True], ['bed', 649, False], ['den', 767, False]],
     [['living', 722, True]],
     [['living', 686, True], ['bed', 715, False], ['den', 617, False], ['office', 250, False]],
     [['living', 790, True]]]],
   [722, 688, 728, 771, 686, 734, 708, 722, 686, 790]],
  ['regression: scenario 2',
   [[[['living', 663, False], ['bed', 781, True], ['den', 775, False], ['office', 722, True]],
     [['living', 655, False]],
     [['living', 777, False], ['bed', 790, True], ['den', 637, False], ['office', 682, False]],
     [['living', 250, False], ['bed', 701, True], ['den', 745, True], ['office', 626, False]],
     [['living', 619, False]],
     [['living', 619, True], ['bed', 710, True]],
     [['living', 732, False]],
     [['living', 772, False]],
     [['living', None, True], ['bed', 664, True], ['den', 728, True], ['office', 783, False]],
     [['living', 1100, True], ['bed', 734, True], ['den', 657, False], ['office', 601, False]]]],
   [752, 655, 790, 723, 619, 665, 732, 772, 696, 734]],
  ['regression: occupancy and faults',
   [[[['liv', 700, True], ['bed', 680, False]],
     [['liv', None, True], ['bed', 681, False], ['den', 690, False]],
     [['liv', 1200, True]],
     [['liv', 701, True], ['bed', 702, True]]]],
   [700, 686, 686, 702]],
  ['regression: shorted sensor',
   [[[['a', 700, True], ['b', 5, True]], [['a', 1300, False], ['b', 690, False]]]],
   [700, 690]],
  ['control: first sample all invalid',
   [[[['a', None, True]], [['a', 700, True]], [['a', None, False]]]],
   [None, 700, 700]],
  ['control: single occupied room',
   [[[['a', 700, True], ['b', 650, False], ['c', 660, False]], [['a', 707, True], ['b', 704, True]]]],
   [700, 706]],
  ['regression: scenario 3',
   [[[['living', 740, True], ['bed', None, False], ['den', 718, True], ['office', 628, True]],
     [['living', 687, True]],
     [['living', 766, True], ['bed', 604, False], ['den', 725, False], ['office', 735, False]],
     [['living', 788, False], ['bed', 698, False], ['den', 700, False], ['office', None, True]],
     [['living', None, False], ['bed', 607, True], ['den', 754, False]],
     [['living', 250, False], ['bed', 649, True], ['den', 666, False]],
     [['living', None, True], ['bed', 785, True]],
     [['living', 715, True], ['bed', 699, False], ['den', 1100, True]],
     [['living', 605, False], ['bed', 735, False]]]],
   [695, 687, 766, 729, 607, 649, 785, 715, 670]],
  ['regression: scenario 4',
   [[[['living', 647, True], ['bed', 693, False]],
     [['living', None, False], ['bed', 1100, False], ['den', None, True], ['office', None, False]],
     [['living', 791, False], ['bed', 250, False], ['den', 778, True]],
     [['living', 650, False], ['bed', None, True]],
     [['living', 1100, True], ['bed', 680, False], ['den', 250, False]],
     [['living', 700, True], ['bed', 1100, True], ['den', 712, False]],
     [['living', 662, True], ['bed', 670, True]]]],
   [647, 647, 778, 650, 680, 700, 666]]],
 [['regression: scenario 4',
   [[[['living', 614, False]],
     [['living', 616, True], ['bed', None, True], ['den', 783, True]],
     [['living', 250, True], ['bed', 250, True]],
     [['living', None, True]],
     [['living', 663, True]],
     [['living', 656, True], ['bed', 250, True], ['den', 679, True]],
     [['living', 799, True], ['bed', 707, True], ['den', 751, True]],
     [['living', None, True]]]],
   [614, 700, 700, 700, 663, 668, 752, 752]],
  ['regression: scenario 7',
   [[[['living', 776, True], ['bed', 1100, False], ['den', 734, False]],
     [['living', 250, True], ['bed', 734, False], ['den', 775, True], ['office', 1100, False]],
     [['living', 250, False], ['bed', 747, True], ['den', None, True]],
     [['living', 622, True], ['bed', 623, False], ['den', 793, True]],
     [['living', 728, True], ['bed', 708, True], ['den', None, False]],
     [['living', 644, False]],
     [['living', 765, True], ['bed', 650, True], ['den', 749, False], ['office', 1100, False]],
     [['living', 672, False], ['bed', 769, True], ['den', 1100, True]],
     [['living', 729, True], ['bed', None, False]],
     [['living', 794, False], ['bed', 670, True]]]],
   [776, 775, 747, 708, 718, 644, 708, 769, 729, 670]],
  ['regression: occupancy and faults',
   [[[['liv', 700, True], ['bed', 680, False]],
     [['liv', None, True], ['bed', 681, False], ['den', 690, False]],
     [['liv', 1200, True]],
     [['liv', 701, True], ['bed', 702, True]]]],
   [700, 686, 686, 702]],
  ['regression: shorted sensor',
   [[[['a', 700, True], ['b', 5, True]], [['a', 1300, False], ['b', 690, False]]]],
   [700, 690]],
  ['control: first sample all invalid',
   [[[['a', None, True]], [['a', 700, True]], [['a', None, False]]]],
   [None, 700, 700]],
  ['control: single occupied room',
   [[[['a', 700, True], ['b', 650, False], ['c', 660, False]], [['a', 707, True], ['b', 704, True]]]],
   [700, 706]],
  ['control: scenario 1',
   [[[['living', 782, False], ['bed', 708, True], ['den', 678, True]],
     [['living', 772, False], ['bed', 795, True]],
     [['living', 744, True], ['bed', 616, True], ['den', 694, True]],
     [['living', 790, False], ['bed', 733, True]],
     [['living', 722, True], ['bed', 701, False]],
     [['living', 699, False], ['bed', 636, False]]]],
   [693, 795, 685, 733, 722, 668]],
  ['regression: scenario 2',
   [[[['living', 675, False], ['bed', 659, True], ['den', 738, False], ['office', 1100, False]],
     [['living', 250, True], ['bed', 649, True]],
     [['living', 604, True]],
     [['living', 629, True], ['bed', None, True], ['den', 610, True]],
     [['living', 633, False], ['bed', None, True], ['den', 778, True], ['office', 795, False]],
     [['living', None, False]]]],
   [659, 649, 604, 620, 778, 778]]],
 [['regression: scenario 3',
   [[[['living', None, True], ['bed', 631, True]],
     [['living', 654, False], ['bed', 779, False], ['den', 716, True]],
     [['living', 799, True]],
     [['living', 664, True]],
     [['living', 622, False]],
     [['living', 697, False], ['bed', 685, False]],
     [['living', 727, False], ['bed', 250, True], ['den', 737, False], ['office', 692, False]]]],
   [631, 716, 799, 664, 622, 691, 719]],
  ['regression: scenario 6',
   [[[['living', 696, False], ['bed', 633, True]],
     [['living', 662, False], ['bed', 1100, False]],
     [['living', 654, True]],
     [['living', 773, True], ['bed', 789, False], ['den', 791, True], ['office', 696, True]],
     [['living', 709, True], ['bed', 753, False]]]],
   [633, 662, 654, 753, 709]],
  ['regression: occupancy and faults',
   [[[['liv', 700, True], ['bed', 680, False]],
     [['liv', None, True], ['bed', 681, False], ['den', 690, False]],
     [['liv', 1200, True]],
     [['liv', 701, True], ['bed', 702, True]]]],
   [700, 686, 686, 702]],
  ['regression: shorted sensor',
   [[[['a', 700, True], ['b', 5, True]], [['a', 1300, False], ['b', 690, False]]]],
   [700, 690]],
  ['control: first sample all invalid',
   [[[['a', None, True]], [['a', 700, True]], [['a', None, False]]]],
   [None, 700, 700]],
  ['control: single occupied room',
   [[[['a', 700, True], ['b', 650, False], ['c', 660, False]], [['a', 707, True], ['b', 704, True]]]],
   [700, 706]],
  ['regression: scenario 1',
   [[[['living', 1100, True]],
     [['living', 634, False], ['bed', 740, False], ['den', None, True]],
     [['living', 1100, True]],
     [['living', 618, False], ['bed', 787, False], ['den', 754, False]],
     [['living', 673, False], ['bed', 795, True], ['den', 612, False], ['office', 721, True]]]],
   [None, 687, 687, 720, 758]],
  ['regression: scenario 2',
   [[[['living', 733, True], ['bed', 629, True], ['den', 631, True], ['office', 649, True]],
     [['living', 766, True]],
     [['living', 727, False], ['bed', 610, False]],
     [['living', None, True]],
     [['living', 627, False]],
     [['living', 689, True], ['bed', 635, True], ['den', 250, False]],
     [['living', 613, False], ['bed', 717, False]],
     [['living', 1100, True]]]],
   [661, 766, 669, 669, 627, 662, 665, 665]]]]
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 shorted or open remote sensor drags the control temperature to an absurd value.

Thermostat with remote room sensors; each sample is a list of [room, reading tenths F or None, occupied]. Readings outside 32.0-100.0 F or None are invalid. The control temperature is the mean of valid readings from occupied rooms, or of all valid readings if no occupied room has one, rounded half up to a tenth; if nothing is valid the previous control temperature is held (None initially). Return the control temperature per sample.

split: open-access