FAILURE MAP
← Case archive

FA-92821 / HVAC thermostat control / Open access

Zoned system never serves a minority mode · case 01

A single zone calling heat waits indefinitely while two zones keep calling cooling.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The forced switch after max_run also requires the other mode to have at least as many calls.

VERIFIED REPAIR

Switch whenever the opposite mode is waiting and max_run has elapsed.

Unsuccessful approach: Switching one minute later than max_run still starves the waiting zone.

Case contract

Zoned single-unit system arbitration per minute; each sample maps zone -> heat, cool or None. When idle the system picks the mode with more calling zones (ties go to heat). A mode ends when no zone calls for it, and a new mode may be chosen in the same minute. If zones call for the opposite mode, the system switches once the current mode has run max_run minutes, restarting the run timer. Dampers open only for zones calling the active mode. Return [mode, sorted open zones] per minute.

Why this case matters

Residential and light-commercial thermostats make these decisions sample by sample; each defect changes equipment calls in a way that shows up as short cycling, comfort complaints or equipment stress.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(max_run, samples):
    mode = None
    since = 0
    out = []
    for minute, calls in enumerate(samples):
        heat = sorted(z for z, c in calls.items() if c == 'heat')
        cool = sorted(z for z, c in calls.items() if c == 'cool')
        want = {'heat': heat, 'cool': cool}
        if mode is not None:
            other = 'cool' if mode == 'heat' else 'heat'
            if not want[mode]:
                mode = None
            elif want[other] and minute - since >= max_run and len(want[other]) >= len(want[mode]):
                mode = other
                since = minute
        if mode is None and (heat or cool):
            mode = 'heat' if len(heat) >= len(cool) else 'cool'
            since = minute
        out.append([mode, want[mode] if mode else []])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: scenario 1',
   [5,
    [{'z1': 'cool', 'z3': None, 'z4': None},
     {'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z2': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'}]],
   [['cool', ['z1']],
    ['cool', ['z4']],
    ['cool', ['z4']],
    ['cool', ['z4']],
    ['cool', ['z2', 'z3', 'z4']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z4']],
    ['heat', ['z3', 'z4']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 2',
   [5,
    [{'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': 'cool', 'z2': None, 'z3': 'heat'},
     {'z1': 'cool', 'z2': None, 'z3': 'heat'},
     {'z1': 'heat'},
     {'z1': 'heat', 'z2': None, 'z4': None},
     {'z1': 'heat', 'z4': None},
     {'z1': 'heat', 'z2': None, 'z4': None},
     {'z1': 'heat', 'z3': 'heat', 'z4': None}]],
   [['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1', 'z3']]]],
  ['regression: scenario 3',
   [2,
    [{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': None},
     {'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': 'cool', 'z2': None, 'z3': 'heat'},
     {'z1': 'cool', 'z3': 'heat'}]],
   [['cool', ['z1', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['heat', ['z2']],
    ['heat', ['z2', 'z4']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['cool', ['z1']]]]],
 [['regression: scenario 2',
   [3,
    [{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'cool'},
     {'z3': 'cool'},
     {'z2': None, 'z3': 'cool', 'z4': None},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
   [['heat', ['z3', 'z4']],
    ['heat', ['z3', 'z4']],
    ['cool', ['z3', 'z4']],
    ['cool', ['z3']],
    ['cool', ['z3']],
    ['heat', ['z1']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z1', 'z2']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 1',
   [3,
    [{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool'}]],
   [['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['cool', ['z4']],
    ['heat', ['z1', 'z3']],
    ['heat', ['z1', 'z3']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z2', 'z4']],
    ['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2', 'z3']],
    ['cool', ['z3']]]],
  ['regression: scenario 3',
   [3,
    [{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'}]],
   [['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z2']],
    ['cool', ['z2']],
    ['cool', ['z2']],
    ['heat', ['z4']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2']]]]],
 [['regression: scenario 3',
   [2,
    [{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z2': 'cool', 'z3': 'cool'},
     {'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'}]],
   [['heat', ['z1', 'z3']],
    ['heat', ['z1', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z3', 'z4']],
    ['heat', ['z2', 'z4']]]],
  ['regression: scenario 1',
   [3,
    [{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': None},
     {'z1': 'heat', 'z2': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': None}]],
   [['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2']],
    ['cool', ['z3', 'z4']],
    ['cool', ['z3']],
    ['cool', ['z3']],
    ['heat', ['z1', 'z2', 'z4']],
    ['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2']],
    ['cool', ['z4']],
    ['heat', ['z1', 'z2']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 2',
   [2,
    [{'z1': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z2': 'cool', 'z4': 'heat'},
     {'z3': None}]],
   [['cool', ['z3', 'z4']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z2']],
    ['cool', ['z2']],
    ['heat', ['z4']],
    [None, []]]]],
 [['regression: scenario 7',
   [2,
    [{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': None, 'z2': 'cool', 'z3': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z3': 'cool'},
     {'z1': 'heat', 'z2': None, 'z3': None, 'z4': 'heat'},
     {'z1': None}]],
   [['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['cool', ['z2', 'z4']],
    ['cool', ['z2', 'z4']],
    ['heat', ['z1']],
    ['heat', ['z1', 'z3']],
    ['cool', ['z1', 'z2']],
    ['cool', ['z2']],
    ['heat', ['z1', 'z3']],
    ['heat', ['z1']],
    ['heat', ['z1', 'z4']],
    [None, []]]],
  ['regression: scenario 3',
   [5,
    [{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
   [['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z1', 'z4']],
    ['cool', ['z2', 'z3']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 1',
   [5,
    [{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z2': 'heat', 'z3': 'heat', 'z4': 'cool'}]],
   [['heat', ['z2', 'z4']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z3']],
    ['cool', ['z1']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2']],
    ['heat', ['z2']],
    ['heat', ['z2', 'z3']]]]],
 [['regression: scenario 8',
   [5,
    [{'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
   [['cool', ['z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z4']],
    ['heat', ['z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']]]],
  ['regression: scenario 3',
   [2,
    [{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z3': 'heat', 'z4': 'cool'}]],
   [['cool', ['z2', 'z3', 'z4']],
    ['cool', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z2', 'z3', 'z4']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z4']],
    ['heat', ['z3']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 1',
   [3,
    [{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat'},
     {'z2': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z3': None, 'z4': 'heat'},
     {'z2': 'heat', 'z3': None, 'z4': 'heat'}]],
   [['heat', ['z1', 'z2', 'z3', 'z4']],
    ['heat', ['z1', 'z2', 'z3']],
    ['heat', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z3']],
    ['cool', ['z3']],
    ['heat', ['z2']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2', 'z4']]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: scenario 1[['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['cool', ['z2', 'z3', 'z4']], ['cool', ['z2', 'z4']], ['cool', ['z2', 'z4']], ['heat', ['z4']], ['heat', ['z3', 'z4']]][['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z4']], ['heat', ['z3', 'z4']]]Failed
regression: majority then forced switch[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]][['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]Passed
control: tie goes to heat[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]][['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]Passed
regression: ping pong guard[['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']]][['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]Passed
control: satisfied then opposite[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]][['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]Passed
control: first minute call[['cool', ['a']], ['cool', ['a']], [None, []]][['cool', ['a']], ['cool', ['a']], [None, []]]Passed
regression: scenario 2[['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]][['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]]Passed
regression: scenario 3[['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z2', 'z4']], ['heat', ['z4']], ['cool', ['z1', 'z3']], ['cool', ['z1']], ['heat', ['z3']], ['heat', ['z3']]][['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['heat', ['z2']], ['heat', ['z2', 'z4']], ['cool', ['z1', 'z2', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['cool', ['z1']]]Failed

SHA-256 / 32bd6a9b5044b3305987cbc98243c60860d6d7559b517d3cc0c6033963058fb6

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(max_run, samples):
    mode = None
    since = 0
    out = []
    for minute, calls in enumerate(samples):
        heat = sorted(z for z, c in calls.items() if c == 'heat')
        cool = sorted(z for z, c in calls.items() if c == 'cool')
        want = {'heat': heat, 'cool': cool}
        if mode is not None:
            other = 'cool' if mode == 'heat' else 'heat'
            if not want[mode]:
                mode = None
            elif want[other] and minute - since > max_run:
                mode = other
                since = minute
        if mode is None and (heat or cool):
            mode = 'heat' if len(heat) >= len(cool) else 'cool'
            since = minute
        out.append([mode, want[mode] if mode else []])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: scenario 1',
   [5,
    [{'z1': 'cool', 'z3': None, 'z4': None},
     {'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z2': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'}]],
   [['cool', ['z1']],
    ['cool', ['z4']],
    ['cool', ['z4']],
    ['cool', ['z4']],
    ['cool', ['z2', 'z3', 'z4']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z4']],
    ['heat', ['z3', 'z4']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 2',
   [5,
    [{'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': 'cool', 'z2': None, 'z3': 'heat'},
     {'z1': 'cool', 'z2': None, 'z3': 'heat'},
     {'z1': 'heat'},
     {'z1': 'heat', 'z2': None, 'z4': None},
     {'z1': 'heat', 'z4': None},
     {'z1': 'heat', 'z2': None, 'z4': None},
     {'z1': 'heat', 'z3': 'heat', 'z4': None}]],
   [['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1', 'z3']]]],
  ['regression: scenario 3',
   [2,
    [{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': None},
     {'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': 'cool', 'z2': None, 'z3': 'heat'},
     {'z1': 'cool', 'z3': 'heat'}]],
   [['cool', ['z1', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['heat', ['z2']],
    ['heat', ['z2', 'z4']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['cool', ['z1']]]]],
 [['regression: scenario 2',
   [3,
    [{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'cool'},
     {'z3': 'cool'},
     {'z2': None, 'z3': 'cool', 'z4': None},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
   [['heat', ['z3', 'z4']],
    ['heat', ['z3', 'z4']],
    ['cool', ['z3', 'z4']],
    ['cool', ['z3']],
    ['cool', ['z3']],
    ['heat', ['z1']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z1', 'z2']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 1',
   [3,
    [{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool'}]],
   [['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['cool', ['z4']],
    ['heat', ['z1', 'z3']],
    ['heat', ['z1', 'z3']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z2', 'z4']],
    ['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2', 'z3']],
    ['cool', ['z3']]]],
  ['regression: scenario 3',
   [3,
    [{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'}]],
   [['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z2']],
    ['cool', ['z2']],
    ['cool', ['z2']],
    ['heat', ['z4']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2']]]]],
 [['regression: scenario 3',
   [2,
    [{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z2': 'cool', 'z3': 'cool'},
     {'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'}]],
   [['heat', ['z1', 'z3']],
    ['heat', ['z1', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z3', 'z4']],
    ['heat', ['z2', 'z4']]]],
  ['regression: scenario 1',
   [3,
    [{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': None},
     {'z1': 'heat', 'z2': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': None}]],
   [['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2']],
    ['cool', ['z3', 'z4']],
    ['cool', ['z3']],
    ['cool', ['z3']],
    ['heat', ['z1', 'z2', 'z4']],
    ['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2']],
    ['cool', ['z4']],
    ['heat', ['z1', 'z2']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 2',
   [2,
    [{'z1': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z2': 'cool', 'z4': 'heat'},
     {'z3': None}]],
   [['cool', ['z3', 'z4']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z2']],
    ['cool', ['z2']],
    ['heat', ['z4']],
    [None, []]]]],
 [['regression: scenario 7',
   [2,
    [{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': None, 'z2': 'cool', 'z3': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z3': 'cool'},
     {'z1': 'heat', 'z2': None, 'z3': None, 'z4': 'heat'},
     {'z1': None}]],
   [['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['cool', ['z2', 'z4']],
    ['cool', ['z2', 'z4']],
    ['heat', ['z1']],
    ['heat', ['z1', 'z3']],
    ['cool', ['z1', 'z2']],
    ['cool', ['z2']],
    ['heat', ['z1', 'z3']],
    ['heat', ['z1']],
    ['heat', ['z1', 'z4']],
    [None, []]]],
  ['regression: scenario 3',
   [5,
    [{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
   [['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z1', 'z4']],
    ['cool', ['z2', 'z3']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 1',
   [5,
    [{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z2': 'heat', 'z3': 'heat', 'z4': 'cool'}]],
   [['heat', ['z2', 'z4']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z3']],
    ['cool', ['z1']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2']],
    ['heat', ['z2']],
    ['heat', ['z2', 'z3']]]]],
 [['regression: scenario 8',
   [5,
    [{'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
   [['cool', ['z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z4']],
    ['heat', ['z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']]]],
  ['regression: scenario 3',
   [2,
    [{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z3': 'heat', 'z4': 'cool'}]],
   [['cool', ['z2', 'z3', 'z4']],
    ['cool', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z2', 'z3', 'z4']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z4']],
    ['heat', ['z3']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 1',
   [3,
    [{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat'},
     {'z2': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z3': None, 'z4': 'heat'},
     {'z2': 'heat', 'z3': None, 'z4': 'heat'}]],
   [['heat', ['z1', 'z2', 'z3', 'z4']],
    ['heat', ['z1', 'z2', 'z3']],
    ['heat', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z3']],
    ['cool', ['z3']],
    ['heat', ['z2']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2', 'z4']]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: scenario 1[['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['cool', ['z2', 'z3', 'z4']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z4']], ['heat', ['z3', 'z4']]][['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z4']], ['heat', ['z3', 'z4']]]Failed
regression: majority then forced switch[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], [None, []]][['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]Failed
control: tie goes to heat[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]][['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]Passed
regression: ping pong guard[['heat', ['a']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']]][['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]Failed
control: satisfied then opposite[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]][['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]Passed
control: first minute call[['cool', ['a']], ['cool', ['a']], [None, []]][['cool', ['a']], ['cool', ['a']], [None, []]]Passed
regression: scenario 2[['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]][['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]]Failed
regression: scenario 3[['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['heat', ['z2']], ['heat', ['z2', 'z4']], ['heat', ['z4']], ['cool', ['z1', 'z3']], ['cool', ['z1']], ['cool', ['z1']], ['heat', ['z3']]][['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['heat', ['z2']], ['heat', ['z2', 'z4']], ['cool', ['z1', 'z2', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['cool', ['z1']]]Failed

SHA-256 / f0fd7e97dc401eb7194f2019a5846d74dac504ff71e952cd05bf8d6dcd248b8d

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(max_run, samples):
    mode = None
    since = 0
    out = []
    for minute, calls in enumerate(samples):
        heat = sorted(z for z, c in calls.items() if c == 'heat')
        cool = sorted(z for z, c in calls.items() if c == 'cool')
        want = {'heat': heat, 'cool': cool}
        if mode is not None:
            other = 'cool' if mode == 'heat' else 'heat'
            if not want[mode]:
                mode = None
            elif want[other] and minute - since >= max_run:
                mode = other
                since = minute
        if mode is None and (heat or cool):
            mode = 'heat' if len(heat) >= len(cool) else 'cool'
            since = minute
        out.append([mode, want[mode] if mode else []])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: scenario 1',
   [5,
    [{'z1': 'cool', 'z3': None, 'z4': None},
     {'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z2': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'}]],
   [['cool', ['z1']],
    ['cool', ['z4']],
    ['cool', ['z4']],
    ['cool', ['z4']],
    ['cool', ['z2', 'z3', 'z4']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z4']],
    ['heat', ['z3', 'z4']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 2',
   [5,
    [{'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool'},
     {'z1': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': 'cool', 'z2': None, 'z3': 'heat'},
     {'z1': 'cool', 'z2': None, 'z3': 'heat'},
     {'z1': 'heat'},
     {'z1': 'heat', 'z2': None, 'z4': None},
     {'z1': 'heat', 'z4': None},
     {'z1': 'heat', 'z2': None, 'z4': None},
     {'z1': 'heat', 'z3': 'heat', 'z4': None}]],
   [['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['heat', ['z1', 'z3']]]],
  ['regression: scenario 3',
   [2,
    [{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': None},
     {'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': 'cool', 'z2': None, 'z3': 'heat'},
     {'z1': 'cool', 'z3': 'heat'}]],
   [['cool', ['z1', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['heat', ['z2']],
    ['heat', ['z2', 'z4']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['cool', ['z1']]]]],
 [['regression: scenario 2',
   [3,
    [{'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'cool'},
     {'z3': 'cool'},
     {'z2': None, 'z3': 'cool', 'z4': None},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
   [['heat', ['z3', 'z4']],
    ['heat', ['z3', 'z4']],
    ['cool', ['z3', 'z4']],
    ['cool', ['z3']],
    ['cool', ['z3']],
    ['heat', ['z1']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z1', 'z2']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 1',
   [3,
    [{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool'}]],
   [['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['cool', ['z4']],
    ['heat', ['z1', 'z3']],
    ['heat', ['z1', 'z3']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z3', 'z4']],
    ['heat', ['z1', 'z2', 'z4']],
    ['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2', 'z3']],
    ['cool', ['z3']]]],
  ['regression: scenario 3',
   [3,
    [{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'}]],
   [['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z2']],
    ['cool', ['z2']],
    ['cool', ['z2']],
    ['heat', ['z4']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2']]]]],
 [['regression: scenario 3',
   [2,
    [{'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z2': 'cool', 'z3': 'cool'},
     {'z2': 'cool', 'z3': 'cool', 'z4': None},
     {'z1': None, 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'}]],
   [['heat', ['z1', 'z3']],
    ['heat', ['z1', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z2', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z2', 'z3']],
    ['cool', ['z3', 'z4']],
    ['heat', ['z2', 'z4']]]],
  ['regression: scenario 1',
   [3,
    [{'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': None},
     {'z1': 'heat', 'z2': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'heat', 'z3': None, 'z4': None}]],
   [['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2']],
    ['cool', ['z3', 'z4']],
    ['cool', ['z3']],
    ['cool', ['z3']],
    ['heat', ['z1', 'z2', 'z4']],
    ['heat', ['z1', 'z2']],
    ['heat', ['z1', 'z2']],
    ['cool', ['z4']],
    ['heat', ['z1', 'z2']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 2',
   [2,
    [{'z1': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z1': None, 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z2': 'cool', 'z4': 'heat'},
     {'z3': None}]],
   [['cool', ['z3', 'z4']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z2']],
    ['cool', ['z2']],
    ['heat', ['z4']],
    [None, []]]]],
 [['regression: scenario 7',
   [2,
    [{'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': None, 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': None},
     {'z1': None, 'z2': 'cool', 'z3': 'heat'},
     {'z1': 'heat', 'z2': None, 'z3': 'heat', 'z4': None},
     {'z1': 'heat', 'z3': 'cool'},
     {'z1': 'heat', 'z2': None, 'z3': None, 'z4': 'heat'},
     {'z1': None}]],
   [['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['heat', ['z1']],
    ['heat', ['z1']],
    ['cool', ['z2', 'z4']],
    ['cool', ['z2', 'z4']],
    ['heat', ['z1']],
    ['heat', ['z1', 'z3']],
    ['cool', ['z1', 'z2']],
    ['cool', ['z2']],
    ['heat', ['z1', 'z3']],
    ['heat', ['z1']],
    ['heat', ['z1', 'z4']],
    [None, []]]],
  ['regression: scenario 3',
   [5,
    [{'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
   [['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z1', 'z4']],
    ['cool', ['z2', 'z3']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 1',
   [5,
    [{'z1': 'cool', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': None, 'z3': 'cool', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z4': 'heat'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z2': 'heat', 'z3': 'cool', 'z4': 'cool'},
     {'z2': 'heat', 'z3': 'heat', 'z4': 'cool'}]],
   [['heat', ['z2', 'z4']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z3']],
    ['cool', ['z1']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2']],
    ['heat', ['z2']],
    ['heat', ['z2', 'z3']]]]],
 [['regression: scenario 8',
   [5,
    [{'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'heat', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': None, 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'heat'}]],
   [['cool', ['z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z4']],
    ['heat', ['z3']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['heat', ['z4']],
    ['cool', ['z1', 'z2', 'z3']],
    ['cool', ['z1', 'z2', 'z3']]]],
  ['regression: scenario 3',
   [2,
    [{'z1': 'heat', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z2': 'cool', 'z3': 'cool', 'z4': 'cool'},
     {'z1': None, 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z2': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z3': 'heat', 'z4': 'cool'},
     {'z1': 'cool', 'z3': 'heat', 'z4': 'cool'}]],
   [['cool', ['z2', 'z3', 'z4']],
    ['cool', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z2', 'z3', 'z4']],
    ['heat', ['z3']],
    ['heat', ['z3']],
    ['cool', ['z1', 'z2', 'z4']],
    ['cool', ['z1', 'z4']],
    ['heat', ['z3']]]],
  ['regression: majority then forced switch',
   [3,
    [{'a': 'heat', 'b': 'cool', 'c': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat'},
     {}]],
   [['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]],
  ['control: tie goes to heat',
   [2, [{'a': 'heat', 'b': 'cool'}, {'a': 'heat', 'b': 'cool'}, {'b': 'cool'}]],
   [['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]],
  ['regression: ping pong guard',
   [2,
    [{'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'},
     {'a': 'heat', 'b': 'cool'}]],
   [['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']],
    ['cool', ['b']],
    ['heat', ['a']],
    ['heat', ['a']],
    ['cool', ['b']]]],
  ['control: satisfied then opposite',
   [5, [{'a': 'cool'}, {'a': 'cool', 'b': 'heat'}, {'b': 'heat'}, {'b': 'heat'}]],
   [['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]],
  ['control: first minute call',
   [3, [{'a': 'cool'}, {'a': 'cool'}, {}]],
   [['cool', ['a']], ['cool', ['a']], [None, []]]],
  ['regression: scenario 1',
   [3,
    [{'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'heat', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z1': 'heat', 'z2': 'heat', 'z3': 'cool', 'z4': 'heat'},
     {'z2': 'heat'},
     {'z2': 'heat', 'z4': 'heat'},
     {'z1': None, 'z2': 'heat', 'z3': None, 'z4': 'heat'},
     {'z2': 'heat', 'z3': None, 'z4': 'heat'}]],
   [['heat', ['z1', 'z2', 'z3', 'z4']],
    ['heat', ['z1', 'z2', 'z3']],
    ['heat', ['z1', 'z2', 'z3', 'z4']],
    ['cool', ['z3']],
    ['cool', ['z3']],
    ['heat', ['z2']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2', 'z4']],
    ['heat', ['z2', 'z4']]]]]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: scenario 1[['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z4']], ['heat', ['z3', 'z4']]][['cool', ['z1']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z4']], ['cool', ['z2', 'z3', 'z4']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z4']], ['heat', ['z3', 'z4']]]Passed
regression: majority then forced switch[['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]][['cool', ['b', 'c']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], [None, []]]Passed
control: tie goes to heat[['heat', ['a']], ['heat', ['a']], ['cool', ['b']]][['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]Passed
regression: ping pong guard[['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']]][['heat', ['a']], ['heat', ['a']], ['cool', ['b']], ['cool', ['b']], ['heat', ['a']], ['heat', ['a']], ['cool', ['b']]]Passed
control: satisfied then opposite[['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]][['cool', ['a']], ['cool', ['a']], ['heat', ['b']], ['heat', ['b']]]Passed
control: first minute call[['cool', ['a']], ['cool', ['a']], [None, []]][['cool', ['a']], ['cool', ['a']], [None, []]]Passed
regression: scenario 2[['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]][['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z3']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1']], ['heat', ['z1', 'z3']]]Passed
regression: scenario 3[['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['heat', ['z2']], ['heat', ['z2', 'z4']], ['cool', ['z1', 'z2', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['cool', ['z1']]][['cool', ['z1', 'z3']], ['cool', ['z2', 'z3']], ['cool', ['z1', 'z2', 'z3']], ['heat', ['z2']], ['heat', ['z2', 'z4']], ['cool', ['z1', 'z2', 'z3']], ['cool', ['z1', 'z3']], ['heat', ['z3']], ['heat', ['z3']], ['cool', ['z1']]]Passed

SHA-256 / c1a86f58ffbe2d7e2de9fdc20c8ad4d10740780e265611f4cd36bb0096ae72d6

Verification & scope

A deterministic bounded teaching model of one thermostat or HVAC controller decision evaluated per sample. Temperatures are integer tenths of a degree Fahrenheit unless stated otherwise. The contract is a stipulated toy convention, not a claim of conformance to any manufacturer, ASHRAE guideline or code. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:51:49.411382+00:00.

Case digest / 6abc41d9f3fd8d83cac3ebd43326b6ccf67ea4d727ece62a041e0fcbf83aaa2a