FAILURE MAP
← Case archive

FA-94726 / Exam timetabling constraints / Open access

Sitting reported once per matching rule · case 01

Overlapping rules (sat and fri-pm style) produce duplicate findings.

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

ROOT CAUSE

Rule matching continues after the first match.

VERIFIED REPAIR

Stop after the first matching rule for a sitting.

Unsuccessful approach: Global deduplication also merges genuinely repeated sitting rows.

Case contract

sits [student, exam, period]; periods index -> [weekday 0=Mon..6=Sun, slot am/pm/eve]; avoid student -> rules "day" (whole day) or "day-slot" (that slot and later slots that day). Each sitting matching any rule is reported once as [student, exam, period]; return rows sorted.

Why this case matters

Religious-observance and other unavailability constraints are student-specific hard constraints.

1 / The failure

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

N = 1
observations = []
def solve(sits, periods, avoid):
    names = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
    order = ['am', 'pm', 'eve']
    out = []
    for st, ex, p in sits:
        wd, slot = periods[p]
        for rule in avoid.get(st, []):
            parts = rule.split('-')
            if parts[0] != names[wd]:
                continue
            if len(parts) == 1 or order.index(slot) >= order.index(parts[1]):
                out.append([st, ex, p])
    return sorted(out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: one row per sitting 1', [[['s1', 'A', 0]], [[4, 'eve']], {'s1': ['fri-eve', 'fri-pm']}],
   [['s1', 'A', 0]]),
  ('regression variant: one row per sitting 2',
   [[['s2', 'MATH101H', 3], ['s1', 'CHEM120', 1], ['s1', 'CHEM120', 3], ['s2', 'MATH101', 0],
     ['s1', 'BIO130', 0], ['s3', 'MATH101', 1]],
    [[4, 'eve'], [3, 'pm'], [4, 'eve'], [1, 'am'], [3, 'pm'], [6, 'eve']],
    {'s1': ['fri-eve', 'sun-am', 'fri'], 's2': ['fri-eve'], 's3': ['fri-eve', 'mon-eve', 'fri-pm']}],
   [['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]),
  ('partial repair guard 3',
   [[['s3', 'ECON150', 0], ['s3', 'ECON150', 0]],
    [[4, 'pm'], [2, 'eve'], [6, 'am'], [6, 'am'], [5, 'eve'], [6, 'eve']],
    {'s1': ['sun-am', 'fri'], 's2': ['fri-eve', 'fri'], 's3': ['fri-pm']}],
   [['s3', 'ECON150', 0], ['s3', 'ECON150', 0]]),
  ('normal control 4',
   [[['s2', 'ECON150', 4], ['s3', 'MATH101H', 0], ['s1', 'HIST140', 3], ['s1', 'BIO130', 4],
     ['s2', 'CHEM120', 5], ['s3', 'ECON150', 3]],
    [[3, 'pm'], [2, 'pm'], [3, 'am'], [3, 'pm'], [3, 'eve'], [5, 'am']],
    {'s1': ['mon-eve', 'sun-am'], 's2': ['mon-eve'], 's3': ['sat', 'fri-pm', 'fri']}],
   []),
  ('normal control 5',
   [[['s3', 'PHYS110', 5], ['s3', 'ECON150', 5]],
    [[1, 'eve'], [4, 'am'], [4, 'pm'], [3, 'pm'], [4, 'eve'], [1, 'eve']],
    {'s1': ['sun-am'], 's2': ['fri'], 's3': ['fri-eve', 'mon-eve', 'sat']}],
   []),
  ('normal control 6',
   [[['s1', 'CHEM120', 4], ['s3', 'HIST140', 3]],
    [[5, 'pm'], [4, 'am'], [3, 'am'], [2, 'eve'], [4, 'pm'], [1, 'pm']],
    {'s1': ['fri', 'sun-am', 'mon-eve'], 's2': ['sun-am', 'sat'], 's3': ['fri-pm', 'sat', 'fri']}],
   [['s1', 'CHEM120', 4]]),
  ('normal control 7',
   [[['s3', 'PHYS110', 4], ['s2', 'MATH101H', 5], ['s1', 'HIST140', 0], ['s1', 'ECON150', 5],
     ['s1', 'BIO130', 5]],
    [[2, 'pm'], [1, 'am'], [2, 'pm'], [0, 'eve'], [3, 'eve'], [5, 'eve']],
    {'s1': ['fri', 'mon-eve', 'sun-am']}],
   []),
  ('normal control 8',
   [[['s1', 'CHEM120', 3], ['s3', 'HIST140', 1], ['s1', 'CHEM120', 4], ['s2', 'HIST140', 5]],
    [[6, 'am'], [3, 'pm'], [4, 'eve'], [1, 'am'], [6, 'eve'], [1, 'pm']],
    {'s1': ['fri-pm'], 's3': ['mon-eve', 'sat', 'fri-pm']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'HIST140', 2], ['s3', 'MATH101H', 1], ['s1', 'CHEM120', 4], ['s2', 'CHEM120', 4],
     ['s2', 'MATH101', 4], ['s3', 'MATH101H', 5]],
    [[0, 'eve'], [4, 'eve'], [4, 'pm'], [4, 'pm'], [5, 'pm'], [0, 'pm']],
    {'s1': ['fri-eve', 'sat', 'mon-eve'],
     's2': ['mon-eve', 'fri', 'sun-am'],
     's3': ['sun-am', 'fri-pm', 'fri']}],
   [['s1', 'CHEM120', 4], ['s3', 'MATH101H', 1]]),
  ('regression variant: one row per sitting 2',
   [[['s1', 'PHYS110', 2], ['s2', 'BIO130', 0], ['s2', 'ECON150', 3], ['s2', 'ECON150', 5]],
    [[3, 'am'], [2, 'pm'], [4, 'am'], [4, 'eve'], [4, 'eve'], [5, 'am']],
    {'s2': ['sun-am', 'fri-pm', 'fri'], 's3': ['sat', 'sun-am']}],
   [['s2', 'ECON150', 3]]),
  ('partial repair guard 3',
   [[['s2', 'HIST140', 4], ['s1', 'HIST140', 2], ['s1', 'BIO130', 2], ['s3', 'MATH101', 3],
     ['s3', 'MATH101', 3]],
    [[0, 'eve'], [0, 'am'], [4, 'am'], [5, 'pm'], [0, 'eve'], [3, 'pm']],
    {'s1': ['fri', 'fri-pm'], 's2': ['fri-eve', 'fri'], 's3': ['sat']}],
   [['s1', 'BIO130', 2], ['s1', 'HIST140', 2], ['s3', 'MATH101', 3], ['s3', 'MATH101', 3]]),
  ('boundary control 4', [[['s1', 'A', 0]], [[4, 'am']], {'s1': ['fri-pm']}], []),
  ('normal control 5',
   [[['s1', 'HIST140', 0], ['s3', 'ECON150', 3]],
    [[6, 'pm'], [1, 'eve'], [3, 'pm'], [3, 'pm'], [1, 'am'], [4, 'am']],
    {'s1': ['fri-eve', 'fri-pm', 'mon-eve'], 's2': ['sat', 'fri'], 's3': ['sun-am']}],
   []),
  ('normal control 6',
   [[['s1', 'HIST140', 1], ['s3', 'MATH101', 0]],
    [[0, 'eve'], [2, 'pm'], [4, 'pm'], [5, 'pm'], [2, 'pm'], [6, 'pm']],
    {'s1': ['sun-am', 'sat'], 's2': ['fri', 'mon-eve', 'fri-eve']}],
   []),
  ('normal control 7',
   [[['s3', 'MATH101', 3]], [[3, 'pm'], [3, 'eve'], [0, 'eve'], [4, 'pm'], [0, 'pm'], [3, 'pm']],
    {'s1': ['sat', 'fri-eve', 'fri']}],
   []),
  ('normal control 8',
   [[['s1', 'CHEM120', 4], ['s3', 'HIST140', 4], ['s2', 'HIST140', 5], ['s2', 'BIO130', 5],
     ['s2', 'BIO130', 3], ['s1', 'MATH101', 3]],
    [[5, 'eve'], [2, 'pm'], [1, 'am'], [2, 'am'], [2, 'pm'], [1, 'pm']], {'s3': ['fri-eve']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'MATH101', 5], ['s2', 'BIO130', 3], ['s3', 'MATH101H', 0], ['s3', 'CHEM120', 4],
     ['s1', 'MATH101H', 4], ['s2', 'PHYS110', 5]],
    [[4, 'eve'], [3, 'pm'], [1, 'eve'], [0, 'eve'], [4, 'pm'], [0, 'am']],
    {'s2': ['sat', 'fri-pm'], 's3': ['fri-eve', 'fri']}],
   [['s3', 'CHEM120', 4], ['s3', 'MATH101H', 0]]),
  ('regression variant: one row per sitting 2',
   [[['s2', 'MATH101H', 3], ['s1', 'CHEM120', 1], ['s1', 'CHEM120', 3], ['s2', 'MATH101', 0],
     ['s1', 'BIO130', 0], ['s3', 'MATH101', 1]],
    [[4, 'eve'], [3, 'pm'], [4, 'eve'], [1, 'am'], [3, 'pm'], [6, 'eve']],
    {'s1': ['fri-eve', 'sun-am', 'fri'], 's2': ['fri-eve'], 's3': ['fri-eve', 'mon-eve', 'fri-pm']}],
   [['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]),
  ('partial repair guard 3',
   [[['s3', 'ECON150', 5], ['s3', 'CHEM120', 0], ['s3', 'CHEM120', 0]],
    [[5, 'pm'], [4, 'eve'], [0, 'eve'], [3, 'eve'], [4, 'am'], [1, 'eve']],
    {'s2': ['sun-am'], 's3': ['sat', 'mon-eve']}],
   [['s3', 'CHEM120', 0], ['s3', 'CHEM120', 0]]),
  ('boundary control 4', [[['s1', 'A', 0]], [[0, 'am']], {'s1': ['sun']}], []),
  ('normal control 5',
   [[['s2', 'ECON150', 5], ['s1', 'ECON150', 2], ['s2', 'HIST140', 0], ['s2', 'PHYS110', 2],
     ['s1', 'HIST140', 3]],
    [[2, 'pm'], [5, 'pm'], [3, 'am'], [6, 'am'], [0, 'am'], [3, 'am']],
    {'s1': ['fri-eve'], 's2': ['fri-eve', 'sun-am']}],
   []),
  ('normal control 6',
   [[['s3', 'CHEM120', 1], ['s3', 'BIO130', 1], ['s1', 'HIST140', 5], ['s2', 'MATH101H', 0],
     ['s1', 'CHEM120', 0]],
    [[3, 'pm'], [3, 'eve'], [1, 'eve'], [0, 'pm'], [5, 'pm'], [2, 'am']],
    {'s1': ['sun-am', 'fri-eve'], 's2': ['mon-eve', 'sat'], 's3': ['fri-eve', 'fri']}],
   []),
  ('normal control 7',
   [[['s2', 'MATH101H', 2], ['s2', 'CHEM120', 1], ['s1', 'MATH101H', 1], ['s2', 'MATH101H', 1],
     ['s3', 'MATH101H', 2], ['s3', 'BIO130', 5]],
    [[0, 'pm'], [0, 'am'], [3, 'eve'], [4, 'am'], [3, 'pm'], [5, 'pm']],
    {'s1': ['mon-eve', 'sat'], 's3': ['sat']}],
   [['s3', 'BIO130', 5]]),
  ('normal control 8',
   [[['s1', 'ECON150', 0], ['s2', 'HIST140', 4]],
    [[3, 'pm'], [4, 'pm'], [5, 'am'], [5, 'eve'], [5, 'am'], [5, 'eve']],
    {'s1': ['sat', 'mon-eve', 'fri'], 's3': ['fri-pm', 'fri', 'sun-am']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'PHYS110', 2], ['s2', 'BIO130', 0], ['s2', 'ECON150', 3], ['s2', 'ECON150', 5]],
    [[3, 'am'], [2, 'pm'], [4, 'am'], [4, 'eve'], [4, 'eve'], [5, 'am']],
    {'s2': ['sun-am', 'fri-pm', 'fri'], 's3': ['sat', 'sun-am']}],
   [['s2', 'ECON150', 3]]),
  ('partial repair guard 2',
   [[['s1', 'MATH101H', 1], ['s3', 'MATH101', 0], ['s3', 'MATH101', 0], ['s2', 'PHYS110', 4],
     ['s2', 'BIO130', 1]],
    [[6, 'eve'], [5, 'am'], [5, 'eve'], [0, 'pm'], [5, 'am'], [0, 'pm']],
    {'s1': ['sat', 'mon-eve'], 's2': ['fri'], 's3': ['fri-pm', 'sun-am']}],
   [['s1', 'MATH101H', 1], ['s3', 'MATH101', 0], ['s3', 'MATH101', 0]]),
  ('boundary control 3', [[['s1', 'A', 0]], [[5, 'am']], {'s1': ['sat', 'fri-pm']}], [['s1', 'A', 0]]),
  ('normal control 4',
   [[['s3', 'ECON150', 3]], [[0, 'eve'], [4, 'eve'], [2, 'eve'], [0, 'am'], [4, 'pm'], [6, 'pm']],
    {'s1': ['fri-eve', 'sun-am'], 's2': ['fri', 'sat', 'fri-eve'], 's3': ['fri-eve', 'mon-eve', 'sat']}],
   []),
  ('normal control 5',
   [[['s3', 'BIO130', 0], ['s1', 'HIST140', 5]],
    [[2, 'pm'], [1, 'eve'], [1, 'eve'], [0, 'pm'], [0, 'am'], [0, 'eve']],
    {'s1': ['mon-eve', 'fri-pm'], 's2': ['fri-pm', 'sat'], 's3': ['fri-eve']}],
   [['s1', 'HIST140', 5]]),
  ('normal control 6',
   [[['s2', 'CHEM120', 0], ['s2', 'MATH101', 3], ['s1', 'HIST140', 2], ['s1', 'MATH101H', 1],
     ['s2', 'PHYS110', 1], ['s3', 'PHYS110', 3]],
    [[1, 'pm'], [4, 'pm'], [4, 'am'], [3, 'am'], [3, 'eve'], [3, 'eve']], {'s1': ['mon-eve']}],
   []),
  ('normal control 7',
   [[['s1', 'HIST140', 4]], [[4, 'eve'], [3, 'am'], [5, 'eve'], [6, 'pm'], [6, 'eve'], [6, 'pm']],
    {'s1': ['fri-pm', 'fri-eve', 'sun-am'], 's2': ['mon-eve', 'fri'], 's3': ['fri', 'fri-eve']}],
   [['s1', 'HIST140', 4]]),
  ('normal control 8',
   [[['s1', 'MATH101', 3], ['s3', 'BIO130', 1]],
    [[0, 'pm'], [2, 'pm'], [2, 'pm'], [4, 'pm'], [0, 'eve'], [5, 'eve']],
    {'s1': ['mon-eve'], 's2': ['fri', 'sat'], 's3': ['fri-pm', 'sun-am']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'ECON150', 0], ['s2', 'ECON150', 3], ['s2', 'ECON150', 5]],
    [[4, 'am'], [4, 'eve'], [3, 'am'], [4, 'eve'], [0, 'pm'], [2, 'am']],
    {'s1': ['sun-am', 'fri-pm'], 's2': ['mon-eve', 'fri', 'fri-pm'], 's3': ['sat', 'sun-am']}],
   [['s2', 'ECON150', 3]]),
  ('regression variant: one row per sitting 2',
   [[['s2', 'MATH101H', 3], ['s1', 'CHEM120', 1], ['s1', 'CHEM120', 3], ['s2', 'MATH101', 0],
     ['s1', 'BIO130', 0], ['s3', 'MATH101', 1]],
    [[4, 'eve'], [3, 'pm'], [4, 'eve'], [1, 'am'], [3, 'pm'], [6, 'eve']],
    {'s1': ['fri-eve', 'sun-am', 'fri'], 's2': ['fri-eve'], 's3': ['fri-eve', 'mon-eve', 'fri-pm']}],
   [['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]),
  ('partial repair guard 3',
   [[['s3', 'ECON150', 0], ['s3', 'ECON150', 0]],
    [[4, 'pm'], [2, 'eve'], [6, 'am'], [6, 'am'], [5, 'eve'], [6, 'eve']],
    {'s1': ['sun-am', 'fri'], 's2': ['fri-eve', 'fri'], 's3': ['fri-pm']}],
   [['s3', 'ECON150', 0], ['s3', 'ECON150', 0]]),
  ('boundary control 4', [[['s1', 'A', 0]], [[4, 'eve']], {'s1': ['fri-pm']}], [['s1', 'A', 0]]),
  ('normal control 5',
   [[['s3', 'HIST140', 1], ['s3', 'PHYS110', 4], ['s2', 'CHEM120', 2], ['s2', 'MATH101H', 4],
     ['s2', 'CHEM120', 1]],
    [[2, 'pm'], [0, 'pm'], [4, 'eve'], [4, 'pm'], [4, 'pm'], [1, 'am']],
    {'s1': ['mon-eve'], 's3': ['mon-eve', 'fri-eve']}],
   []),
  ('normal control 6',
   [[['s1', 'CHEM120', 3], ['s1', 'BIO130', 4], ['s2', 'ECON150', 4], ['s1', 'HIST140', 0],
     ['s1', 'CHEM120', 1]],
    [[6, 'pm'], [3, 'pm'], [5, 'pm'], [0, 'eve'], [6, 'am'], [1, 'am']],
    {'s1': ['mon-eve', 'fri', 'sun-am'], 's2': ['sat', 'fri-pm', 'fri']}],
   [['s1', 'BIO130', 4], ['s1', 'CHEM120', 3], ['s1', 'HIST140', 0]]),
  ('normal control 7',
   [[['s3', 'CHEM120', 3], ['s2', 'MATH101', 0], ['s3', 'MATH101', 3], ['s3', 'ECON150', 0]],
    [[3, 'eve'], [3, 'pm'], [4, 'eve'], [0, 'am'], [0, 'pm'], [6, 'am']],
    {'s1': ['fri-eve', 'fri', 'sun-am'], 's3': ['fri-eve', 'sun-am', 'sat']}],
   []),
  ('normal control 8',
   [[['s3', 'HIST140', 4]], [[3, 'pm'], [5, 'pm'], [4, 'eve'], [1, 'eve'], [6, 'am'], [1, 'pm']],
    {'s1': ['fri-pm', 'fri-eve'], 's2': ['fri-eve', 'fri-pm'], 's3': ['mon-eve', 'sun-am']}],
   [['s3', 'HIST140', 4]])]]
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: one row per sitting 1[['s1', 'A', 0], ['s1', 'A', 0]][['s1', 'A', 0]]Failed
regression variant: one row per sitting 2[['s1', 'BIO130', 0], ['s1', 'BIO130', 0], ['s2', 'MATH101', 0]][['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]Failed
partial repair guard 3[['s3', 'ECON150', 0], ['s3', 'ECON150', 0]][['s3', 'ECON150', 0], ['s3', 'ECON150', 0]]Passed
normal control 4[][]Passed
normal control 5[][]Passed
normal control 6[['s1', 'CHEM120', 4]][['s1', 'CHEM120', 4]]Passed
normal control 7[][]Passed
normal control 8[][]Passed

SHA-256 / 09a62509ca034eff5f350004a60c380ad97e0506994a42aa88b8c09d1f974dff

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(sits, periods, avoid):
    names = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
    order = ['am', 'pm', 'eve']
    out = []
    for st, ex, p in sits:
        wd, slot = periods[p]
        for rule in avoid.get(st, []):
            parts = rule.split('-')
            if parts[0] != names[wd]:
                continue
            if len(parts) == 1 or order.index(slot) >= order.index(parts[1]):
                if [st, ex, p] not in out:
                    out.append([st, ex, p])
    return sorted(out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: one row per sitting 1', [[['s1', 'A', 0]], [[4, 'eve']], {'s1': ['fri-eve', 'fri-pm']}],
   [['s1', 'A', 0]]),
  ('regression variant: one row per sitting 2',
   [[['s2', 'MATH101H', 3], ['s1', 'CHEM120', 1], ['s1', 'CHEM120', 3], ['s2', 'MATH101', 0],
     ['s1', 'BIO130', 0], ['s3', 'MATH101', 1]],
    [[4, 'eve'], [3, 'pm'], [4, 'eve'], [1, 'am'], [3, 'pm'], [6, 'eve']],
    {'s1': ['fri-eve', 'sun-am', 'fri'], 's2': ['fri-eve'], 's3': ['fri-eve', 'mon-eve', 'fri-pm']}],
   [['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]),
  ('partial repair guard 3',
   [[['s3', 'ECON150', 0], ['s3', 'ECON150', 0]],
    [[4, 'pm'], [2, 'eve'], [6, 'am'], [6, 'am'], [5, 'eve'], [6, 'eve']],
    {'s1': ['sun-am', 'fri'], 's2': ['fri-eve', 'fri'], 's3': ['fri-pm']}],
   [['s3', 'ECON150', 0], ['s3', 'ECON150', 0]]),
  ('normal control 4',
   [[['s2', 'ECON150', 4], ['s3', 'MATH101H', 0], ['s1', 'HIST140', 3], ['s1', 'BIO130', 4],
     ['s2', 'CHEM120', 5], ['s3', 'ECON150', 3]],
    [[3, 'pm'], [2, 'pm'], [3, 'am'], [3, 'pm'], [3, 'eve'], [5, 'am']],
    {'s1': ['mon-eve', 'sun-am'], 's2': ['mon-eve'], 's3': ['sat', 'fri-pm', 'fri']}],
   []),
  ('normal control 5',
   [[['s3', 'PHYS110', 5], ['s3', 'ECON150', 5]],
    [[1, 'eve'], [4, 'am'], [4, 'pm'], [3, 'pm'], [4, 'eve'], [1, 'eve']],
    {'s1': ['sun-am'], 's2': ['fri'], 's3': ['fri-eve', 'mon-eve', 'sat']}],
   []),
  ('normal control 6',
   [[['s1', 'CHEM120', 4], ['s3', 'HIST140', 3]],
    [[5, 'pm'], [4, 'am'], [3, 'am'], [2, 'eve'], [4, 'pm'], [1, 'pm']],
    {'s1': ['fri', 'sun-am', 'mon-eve'], 's2': ['sun-am', 'sat'], 's3': ['fri-pm', 'sat', 'fri']}],
   [['s1', 'CHEM120', 4]]),
  ('normal control 7',
   [[['s3', 'PHYS110', 4], ['s2', 'MATH101H', 5], ['s1', 'HIST140', 0], ['s1', 'ECON150', 5],
     ['s1', 'BIO130', 5]],
    [[2, 'pm'], [1, 'am'], [2, 'pm'], [0, 'eve'], [3, 'eve'], [5, 'eve']],
    {'s1': ['fri', 'mon-eve', 'sun-am']}],
   []),
  ('normal control 8',
   [[['s1', 'CHEM120', 3], ['s3', 'HIST140', 1], ['s1', 'CHEM120', 4], ['s2', 'HIST140', 5]],
    [[6, 'am'], [3, 'pm'], [4, 'eve'], [1, 'am'], [6, 'eve'], [1, 'pm']],
    {'s1': ['fri-pm'], 's3': ['mon-eve', 'sat', 'fri-pm']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'HIST140', 2], ['s3', 'MATH101H', 1], ['s1', 'CHEM120', 4], ['s2', 'CHEM120', 4],
     ['s2', 'MATH101', 4], ['s3', 'MATH101H', 5]],
    [[0, 'eve'], [4, 'eve'], [4, 'pm'], [4, 'pm'], [5, 'pm'], [0, 'pm']],
    {'s1': ['fri-eve', 'sat', 'mon-eve'],
     's2': ['mon-eve', 'fri', 'sun-am'],
     's3': ['sun-am', 'fri-pm', 'fri']}],
   [['s1', 'CHEM120', 4], ['s3', 'MATH101H', 1]]),
  ('regression variant: one row per sitting 2',
   [[['s1', 'PHYS110', 2], ['s2', 'BIO130', 0], ['s2', 'ECON150', 3], ['s2', 'ECON150', 5]],
    [[3, 'am'], [2, 'pm'], [4, 'am'], [4, 'eve'], [4, 'eve'], [5, 'am']],
    {'s2': ['sun-am', 'fri-pm', 'fri'], 's3': ['sat', 'sun-am']}],
   [['s2', 'ECON150', 3]]),
  ('partial repair guard 3',
   [[['s2', 'HIST140', 4], ['s1', 'HIST140', 2], ['s1', 'BIO130', 2], ['s3', 'MATH101', 3],
     ['s3', 'MATH101', 3]],
    [[0, 'eve'], [0, 'am'], [4, 'am'], [5, 'pm'], [0, 'eve'], [3, 'pm']],
    {'s1': ['fri', 'fri-pm'], 's2': ['fri-eve', 'fri'], 's3': ['sat']}],
   [['s1', 'BIO130', 2], ['s1', 'HIST140', 2], ['s3', 'MATH101', 3], ['s3', 'MATH101', 3]]),
  ('boundary control 4', [[['s1', 'A', 0]], [[4, 'am']], {'s1': ['fri-pm']}], []),
  ('normal control 5',
   [[['s1', 'HIST140', 0], ['s3', 'ECON150', 3]],
    [[6, 'pm'], [1, 'eve'], [3, 'pm'], [3, 'pm'], [1, 'am'], [4, 'am']],
    {'s1': ['fri-eve', 'fri-pm', 'mon-eve'], 's2': ['sat', 'fri'], 's3': ['sun-am']}],
   []),
  ('normal control 6',
   [[['s1', 'HIST140', 1], ['s3', 'MATH101', 0]],
    [[0, 'eve'], [2, 'pm'], [4, 'pm'], [5, 'pm'], [2, 'pm'], [6, 'pm']],
    {'s1': ['sun-am', 'sat'], 's2': ['fri', 'mon-eve', 'fri-eve']}],
   []),
  ('normal control 7',
   [[['s3', 'MATH101', 3]], [[3, 'pm'], [3, 'eve'], [0, 'eve'], [4, 'pm'], [0, 'pm'], [3, 'pm']],
    {'s1': ['sat', 'fri-eve', 'fri']}],
   []),
  ('normal control 8',
   [[['s1', 'CHEM120', 4], ['s3', 'HIST140', 4], ['s2', 'HIST140', 5], ['s2', 'BIO130', 5],
     ['s2', 'BIO130', 3], ['s1', 'MATH101', 3]],
    [[5, 'eve'], [2, 'pm'], [1, 'am'], [2, 'am'], [2, 'pm'], [1, 'pm']], {'s3': ['fri-eve']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'MATH101', 5], ['s2', 'BIO130', 3], ['s3', 'MATH101H', 0], ['s3', 'CHEM120', 4],
     ['s1', 'MATH101H', 4], ['s2', 'PHYS110', 5]],
    [[4, 'eve'], [3, 'pm'], [1, 'eve'], [0, 'eve'], [4, 'pm'], [0, 'am']],
    {'s2': ['sat', 'fri-pm'], 's3': ['fri-eve', 'fri']}],
   [['s3', 'CHEM120', 4], ['s3', 'MATH101H', 0]]),
  ('regression variant: one row per sitting 2',
   [[['s2', 'MATH101H', 3], ['s1', 'CHEM120', 1], ['s1', 'CHEM120', 3], ['s2', 'MATH101', 0],
     ['s1', 'BIO130', 0], ['s3', 'MATH101', 1]],
    [[4, 'eve'], [3, 'pm'], [4, 'eve'], [1, 'am'], [3, 'pm'], [6, 'eve']],
    {'s1': ['fri-eve', 'sun-am', 'fri'], 's2': ['fri-eve'], 's3': ['fri-eve', 'mon-eve', 'fri-pm']}],
   [['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]),
  ('partial repair guard 3',
   [[['s3', 'ECON150', 5], ['s3', 'CHEM120', 0], ['s3', 'CHEM120', 0]],
    [[5, 'pm'], [4, 'eve'], [0, 'eve'], [3, 'eve'], [4, 'am'], [1, 'eve']],
    {'s2': ['sun-am'], 's3': ['sat', 'mon-eve']}],
   [['s3', 'CHEM120', 0], ['s3', 'CHEM120', 0]]),
  ('boundary control 4', [[['s1', 'A', 0]], [[0, 'am']], {'s1': ['sun']}], []),
  ('normal control 5',
   [[['s2', 'ECON150', 5], ['s1', 'ECON150', 2], ['s2', 'HIST140', 0], ['s2', 'PHYS110', 2],
     ['s1', 'HIST140', 3]],
    [[2, 'pm'], [5, 'pm'], [3, 'am'], [6, 'am'], [0, 'am'], [3, 'am']],
    {'s1': ['fri-eve'], 's2': ['fri-eve', 'sun-am']}],
   []),
  ('normal control 6',
   [[['s3', 'CHEM120', 1], ['s3', 'BIO130', 1], ['s1', 'HIST140', 5], ['s2', 'MATH101H', 0],
     ['s1', 'CHEM120', 0]],
    [[3, 'pm'], [3, 'eve'], [1, 'eve'], [0, 'pm'], [5, 'pm'], [2, 'am']],
    {'s1': ['sun-am', 'fri-eve'], 's2': ['mon-eve', 'sat'], 's3': ['fri-eve', 'fri']}],
   []),
  ('normal control 7',
   [[['s2', 'MATH101H', 2], ['s2', 'CHEM120', 1], ['s1', 'MATH101H', 1], ['s2', 'MATH101H', 1],
     ['s3', 'MATH101H', 2], ['s3', 'BIO130', 5]],
    [[0, 'pm'], [0, 'am'], [3, 'eve'], [4, 'am'], [3, 'pm'], [5, 'pm']],
    {'s1': ['mon-eve', 'sat'], 's3': ['sat']}],
   [['s3', 'BIO130', 5]]),
  ('normal control 8',
   [[['s1', 'ECON150', 0], ['s2', 'HIST140', 4]],
    [[3, 'pm'], [4, 'pm'], [5, 'am'], [5, 'eve'], [5, 'am'], [5, 'eve']],
    {'s1': ['sat', 'mon-eve', 'fri'], 's3': ['fri-pm', 'fri', 'sun-am']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'PHYS110', 2], ['s2', 'BIO130', 0], ['s2', 'ECON150', 3], ['s2', 'ECON150', 5]],
    [[3, 'am'], [2, 'pm'], [4, 'am'], [4, 'eve'], [4, 'eve'], [5, 'am']],
    {'s2': ['sun-am', 'fri-pm', 'fri'], 's3': ['sat', 'sun-am']}],
   [['s2', 'ECON150', 3]]),
  ('partial repair guard 2',
   [[['s1', 'MATH101H', 1], ['s3', 'MATH101', 0], ['s3', 'MATH101', 0], ['s2', 'PHYS110', 4],
     ['s2', 'BIO130', 1]],
    [[6, 'eve'], [5, 'am'], [5, 'eve'], [0, 'pm'], [5, 'am'], [0, 'pm']],
    {'s1': ['sat', 'mon-eve'], 's2': ['fri'], 's3': ['fri-pm', 'sun-am']}],
   [['s1', 'MATH101H', 1], ['s3', 'MATH101', 0], ['s3', 'MATH101', 0]]),
  ('boundary control 3', [[['s1', 'A', 0]], [[5, 'am']], {'s1': ['sat', 'fri-pm']}], [['s1', 'A', 0]]),
  ('normal control 4',
   [[['s3', 'ECON150', 3]], [[0, 'eve'], [4, 'eve'], [2, 'eve'], [0, 'am'], [4, 'pm'], [6, 'pm']],
    {'s1': ['fri-eve', 'sun-am'], 's2': ['fri', 'sat', 'fri-eve'], 's3': ['fri-eve', 'mon-eve', 'sat']}],
   []),
  ('normal control 5',
   [[['s3', 'BIO130', 0], ['s1', 'HIST140', 5]],
    [[2, 'pm'], [1, 'eve'], [1, 'eve'], [0, 'pm'], [0, 'am'], [0, 'eve']],
    {'s1': ['mon-eve', 'fri-pm'], 's2': ['fri-pm', 'sat'], 's3': ['fri-eve']}],
   [['s1', 'HIST140', 5]]),
  ('normal control 6',
   [[['s2', 'CHEM120', 0], ['s2', 'MATH101', 3], ['s1', 'HIST140', 2], ['s1', 'MATH101H', 1],
     ['s2', 'PHYS110', 1], ['s3', 'PHYS110', 3]],
    [[1, 'pm'], [4, 'pm'], [4, 'am'], [3, 'am'], [3, 'eve'], [3, 'eve']], {'s1': ['mon-eve']}],
   []),
  ('normal control 7',
   [[['s1', 'HIST140', 4]], [[4, 'eve'], [3, 'am'], [5, 'eve'], [6, 'pm'], [6, 'eve'], [6, 'pm']],
    {'s1': ['fri-pm', 'fri-eve', 'sun-am'], 's2': ['mon-eve', 'fri'], 's3': ['fri', 'fri-eve']}],
   [['s1', 'HIST140', 4]]),
  ('normal control 8',
   [[['s1', 'MATH101', 3], ['s3', 'BIO130', 1]],
    [[0, 'pm'], [2, 'pm'], [2, 'pm'], [4, 'pm'], [0, 'eve'], [5, 'eve']],
    {'s1': ['mon-eve'], 's2': ['fri', 'sat'], 's3': ['fri-pm', 'sun-am']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'ECON150', 0], ['s2', 'ECON150', 3], ['s2', 'ECON150', 5]],
    [[4, 'am'], [4, 'eve'], [3, 'am'], [4, 'eve'], [0, 'pm'], [2, 'am']],
    {'s1': ['sun-am', 'fri-pm'], 's2': ['mon-eve', 'fri', 'fri-pm'], 's3': ['sat', 'sun-am']}],
   [['s2', 'ECON150', 3]]),
  ('regression variant: one row per sitting 2',
   [[['s2', 'MATH101H', 3], ['s1', 'CHEM120', 1], ['s1', 'CHEM120', 3], ['s2', 'MATH101', 0],
     ['s1', 'BIO130', 0], ['s3', 'MATH101', 1]],
    [[4, 'eve'], [3, 'pm'], [4, 'eve'], [1, 'am'], [3, 'pm'], [6, 'eve']],
    {'s1': ['fri-eve', 'sun-am', 'fri'], 's2': ['fri-eve'], 's3': ['fri-eve', 'mon-eve', 'fri-pm']}],
   [['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]),
  ('partial repair guard 3',
   [[['s3', 'ECON150', 0], ['s3', 'ECON150', 0]],
    [[4, 'pm'], [2, 'eve'], [6, 'am'], [6, 'am'], [5, 'eve'], [6, 'eve']],
    {'s1': ['sun-am', 'fri'], 's2': ['fri-eve', 'fri'], 's3': ['fri-pm']}],
   [['s3', 'ECON150', 0], ['s3', 'ECON150', 0]]),
  ('boundary control 4', [[['s1', 'A', 0]], [[4, 'eve']], {'s1': ['fri-pm']}], [['s1', 'A', 0]]),
  ('normal control 5',
   [[['s3', 'HIST140', 1], ['s3', 'PHYS110', 4], ['s2', 'CHEM120', 2], ['s2', 'MATH101H', 4],
     ['s2', 'CHEM120', 1]],
    [[2, 'pm'], [0, 'pm'], [4, 'eve'], [4, 'pm'], [4, 'pm'], [1, 'am']],
    {'s1': ['mon-eve'], 's3': ['mon-eve', 'fri-eve']}],
   []),
  ('normal control 6',
   [[['s1', 'CHEM120', 3], ['s1', 'BIO130', 4], ['s2', 'ECON150', 4], ['s1', 'HIST140', 0],
     ['s1', 'CHEM120', 1]],
    [[6, 'pm'], [3, 'pm'], [5, 'pm'], [0, 'eve'], [6, 'am'], [1, 'am']],
    {'s1': ['mon-eve', 'fri', 'sun-am'], 's2': ['sat', 'fri-pm', 'fri']}],
   [['s1', 'BIO130', 4], ['s1', 'CHEM120', 3], ['s1', 'HIST140', 0]]),
  ('normal control 7',
   [[['s3', 'CHEM120', 3], ['s2', 'MATH101', 0], ['s3', 'MATH101', 3], ['s3', 'ECON150', 0]],
    [[3, 'eve'], [3, 'pm'], [4, 'eve'], [0, 'am'], [0, 'pm'], [6, 'am']],
    {'s1': ['fri-eve', 'fri', 'sun-am'], 's3': ['fri-eve', 'sun-am', 'sat']}],
   []),
  ('normal control 8',
   [[['s3', 'HIST140', 4]], [[3, 'pm'], [5, 'pm'], [4, 'eve'], [1, 'eve'], [6, 'am'], [1, 'pm']],
    {'s1': ['fri-pm', 'fri-eve'], 's2': ['fri-eve', 'fri-pm'], 's3': ['mon-eve', 'sun-am']}],
   [['s3', 'HIST140', 4]])]]
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: one row per sitting 1[['s1', 'A', 0]][['s1', 'A', 0]]Passed
regression variant: one row per sitting 2[['s1', 'BIO130', 0], ['s2', 'MATH101', 0]][['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]Passed
partial repair guard 3[['s3', 'ECON150', 0]][['s3', 'ECON150', 0], ['s3', 'ECON150', 0]]Failed
normal control 4[][]Passed
normal control 5[][]Passed
normal control 6[['s1', 'CHEM120', 4]][['s1', 'CHEM120', 4]]Passed
normal control 7[][]Passed
normal control 8[][]Passed

SHA-256 / a0ea1240ec54413aa10fe3fe98cf8e961fbbb5e9299d91bf082bfa9948a5861a

3 / The verified repair

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

N = 1
observations = []
def solve(sits, periods, avoid):
    names = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
    order = ['am', 'pm', 'eve']
    out = []
    for st, ex, p in sits:
        wd, slot = periods[p]
        for rule in avoid.get(st, []):
            parts = rule.split('-')
            if parts[0] != names[wd]:
                continue
            if len(parts) == 1 or order.index(slot) >= order.index(parts[1]):
                out.append([st, ex, p])
                break
    return sorted(out)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: one row per sitting 1', [[['s1', 'A', 0]], [[4, 'eve']], {'s1': ['fri-eve', 'fri-pm']}],
   [['s1', 'A', 0]]),
  ('regression variant: one row per sitting 2',
   [[['s2', 'MATH101H', 3], ['s1', 'CHEM120', 1], ['s1', 'CHEM120', 3], ['s2', 'MATH101', 0],
     ['s1', 'BIO130', 0], ['s3', 'MATH101', 1]],
    [[4, 'eve'], [3, 'pm'], [4, 'eve'], [1, 'am'], [3, 'pm'], [6, 'eve']],
    {'s1': ['fri-eve', 'sun-am', 'fri'], 's2': ['fri-eve'], 's3': ['fri-eve', 'mon-eve', 'fri-pm']}],
   [['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]),
  ('partial repair guard 3',
   [[['s3', 'ECON150', 0], ['s3', 'ECON150', 0]],
    [[4, 'pm'], [2, 'eve'], [6, 'am'], [6, 'am'], [5, 'eve'], [6, 'eve']],
    {'s1': ['sun-am', 'fri'], 's2': ['fri-eve', 'fri'], 's3': ['fri-pm']}],
   [['s3', 'ECON150', 0], ['s3', 'ECON150', 0]]),
  ('normal control 4',
   [[['s2', 'ECON150', 4], ['s3', 'MATH101H', 0], ['s1', 'HIST140', 3], ['s1', 'BIO130', 4],
     ['s2', 'CHEM120', 5], ['s3', 'ECON150', 3]],
    [[3, 'pm'], [2, 'pm'], [3, 'am'], [3, 'pm'], [3, 'eve'], [5, 'am']],
    {'s1': ['mon-eve', 'sun-am'], 's2': ['mon-eve'], 's3': ['sat', 'fri-pm', 'fri']}],
   []),
  ('normal control 5',
   [[['s3', 'PHYS110', 5], ['s3', 'ECON150', 5]],
    [[1, 'eve'], [4, 'am'], [4, 'pm'], [3, 'pm'], [4, 'eve'], [1, 'eve']],
    {'s1': ['sun-am'], 's2': ['fri'], 's3': ['fri-eve', 'mon-eve', 'sat']}],
   []),
  ('normal control 6',
   [[['s1', 'CHEM120', 4], ['s3', 'HIST140', 3]],
    [[5, 'pm'], [4, 'am'], [3, 'am'], [2, 'eve'], [4, 'pm'], [1, 'pm']],
    {'s1': ['fri', 'sun-am', 'mon-eve'], 's2': ['sun-am', 'sat'], 's3': ['fri-pm', 'sat', 'fri']}],
   [['s1', 'CHEM120', 4]]),
  ('normal control 7',
   [[['s3', 'PHYS110', 4], ['s2', 'MATH101H', 5], ['s1', 'HIST140', 0], ['s1', 'ECON150', 5],
     ['s1', 'BIO130', 5]],
    [[2, 'pm'], [1, 'am'], [2, 'pm'], [0, 'eve'], [3, 'eve'], [5, 'eve']],
    {'s1': ['fri', 'mon-eve', 'sun-am']}],
   []),
  ('normal control 8',
   [[['s1', 'CHEM120', 3], ['s3', 'HIST140', 1], ['s1', 'CHEM120', 4], ['s2', 'HIST140', 5]],
    [[6, 'am'], [3, 'pm'], [4, 'eve'], [1, 'am'], [6, 'eve'], [1, 'pm']],
    {'s1': ['fri-pm'], 's3': ['mon-eve', 'sat', 'fri-pm']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'HIST140', 2], ['s3', 'MATH101H', 1], ['s1', 'CHEM120', 4], ['s2', 'CHEM120', 4],
     ['s2', 'MATH101', 4], ['s3', 'MATH101H', 5]],
    [[0, 'eve'], [4, 'eve'], [4, 'pm'], [4, 'pm'], [5, 'pm'], [0, 'pm']],
    {'s1': ['fri-eve', 'sat', 'mon-eve'],
     's2': ['mon-eve', 'fri', 'sun-am'],
     's3': ['sun-am', 'fri-pm', 'fri']}],
   [['s1', 'CHEM120', 4], ['s3', 'MATH101H', 1]]),
  ('regression variant: one row per sitting 2',
   [[['s1', 'PHYS110', 2], ['s2', 'BIO130', 0], ['s2', 'ECON150', 3], ['s2', 'ECON150', 5]],
    [[3, 'am'], [2, 'pm'], [4, 'am'], [4, 'eve'], [4, 'eve'], [5, 'am']],
    {'s2': ['sun-am', 'fri-pm', 'fri'], 's3': ['sat', 'sun-am']}],
   [['s2', 'ECON150', 3]]),
  ('partial repair guard 3',
   [[['s2', 'HIST140', 4], ['s1', 'HIST140', 2], ['s1', 'BIO130', 2], ['s3', 'MATH101', 3],
     ['s3', 'MATH101', 3]],
    [[0, 'eve'], [0, 'am'], [4, 'am'], [5, 'pm'], [0, 'eve'], [3, 'pm']],
    {'s1': ['fri', 'fri-pm'], 's2': ['fri-eve', 'fri'], 's3': ['sat']}],
   [['s1', 'BIO130', 2], ['s1', 'HIST140', 2], ['s3', 'MATH101', 3], ['s3', 'MATH101', 3]]),
  ('boundary control 4', [[['s1', 'A', 0]], [[4, 'am']], {'s1': ['fri-pm']}], []),
  ('normal control 5',
   [[['s1', 'HIST140', 0], ['s3', 'ECON150', 3]],
    [[6, 'pm'], [1, 'eve'], [3, 'pm'], [3, 'pm'], [1, 'am'], [4, 'am']],
    {'s1': ['fri-eve', 'fri-pm', 'mon-eve'], 's2': ['sat', 'fri'], 's3': ['sun-am']}],
   []),
  ('normal control 6',
   [[['s1', 'HIST140', 1], ['s3', 'MATH101', 0]],
    [[0, 'eve'], [2, 'pm'], [4, 'pm'], [5, 'pm'], [2, 'pm'], [6, 'pm']],
    {'s1': ['sun-am', 'sat'], 's2': ['fri', 'mon-eve', 'fri-eve']}],
   []),
  ('normal control 7',
   [[['s3', 'MATH101', 3]], [[3, 'pm'], [3, 'eve'], [0, 'eve'], [4, 'pm'], [0, 'pm'], [3, 'pm']],
    {'s1': ['sat', 'fri-eve', 'fri']}],
   []),
  ('normal control 8',
   [[['s1', 'CHEM120', 4], ['s3', 'HIST140', 4], ['s2', 'HIST140', 5], ['s2', 'BIO130', 5],
     ['s2', 'BIO130', 3], ['s1', 'MATH101', 3]],
    [[5, 'eve'], [2, 'pm'], [1, 'am'], [2, 'am'], [2, 'pm'], [1, 'pm']], {'s3': ['fri-eve']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'MATH101', 5], ['s2', 'BIO130', 3], ['s3', 'MATH101H', 0], ['s3', 'CHEM120', 4],
     ['s1', 'MATH101H', 4], ['s2', 'PHYS110', 5]],
    [[4, 'eve'], [3, 'pm'], [1, 'eve'], [0, 'eve'], [4, 'pm'], [0, 'am']],
    {'s2': ['sat', 'fri-pm'], 's3': ['fri-eve', 'fri']}],
   [['s3', 'CHEM120', 4], ['s3', 'MATH101H', 0]]),
  ('regression variant: one row per sitting 2',
   [[['s2', 'MATH101H', 3], ['s1', 'CHEM120', 1], ['s1', 'CHEM120', 3], ['s2', 'MATH101', 0],
     ['s1', 'BIO130', 0], ['s3', 'MATH101', 1]],
    [[4, 'eve'], [3, 'pm'], [4, 'eve'], [1, 'am'], [3, 'pm'], [6, 'eve']],
    {'s1': ['fri-eve', 'sun-am', 'fri'], 's2': ['fri-eve'], 's3': ['fri-eve', 'mon-eve', 'fri-pm']}],
   [['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]),
  ('partial repair guard 3',
   [[['s3', 'ECON150', 5], ['s3', 'CHEM120', 0], ['s3', 'CHEM120', 0]],
    [[5, 'pm'], [4, 'eve'], [0, 'eve'], [3, 'eve'], [4, 'am'], [1, 'eve']],
    {'s2': ['sun-am'], 's3': ['sat', 'mon-eve']}],
   [['s3', 'CHEM120', 0], ['s3', 'CHEM120', 0]]),
  ('boundary control 4', [[['s1', 'A', 0]], [[0, 'am']], {'s1': ['sun']}], []),
  ('normal control 5',
   [[['s2', 'ECON150', 5], ['s1', 'ECON150', 2], ['s2', 'HIST140', 0], ['s2', 'PHYS110', 2],
     ['s1', 'HIST140', 3]],
    [[2, 'pm'], [5, 'pm'], [3, 'am'], [6, 'am'], [0, 'am'], [3, 'am']],
    {'s1': ['fri-eve'], 's2': ['fri-eve', 'sun-am']}],
   []),
  ('normal control 6',
   [[['s3', 'CHEM120', 1], ['s3', 'BIO130', 1], ['s1', 'HIST140', 5], ['s2', 'MATH101H', 0],
     ['s1', 'CHEM120', 0]],
    [[3, 'pm'], [3, 'eve'], [1, 'eve'], [0, 'pm'], [5, 'pm'], [2, 'am']],
    {'s1': ['sun-am', 'fri-eve'], 's2': ['mon-eve', 'sat'], 's3': ['fri-eve', 'fri']}],
   []),
  ('normal control 7',
   [[['s2', 'MATH101H', 2], ['s2', 'CHEM120', 1], ['s1', 'MATH101H', 1], ['s2', 'MATH101H', 1],
     ['s3', 'MATH101H', 2], ['s3', 'BIO130', 5]],
    [[0, 'pm'], [0, 'am'], [3, 'eve'], [4, 'am'], [3, 'pm'], [5, 'pm']],
    {'s1': ['mon-eve', 'sat'], 's3': ['sat']}],
   [['s3', 'BIO130', 5]]),
  ('normal control 8',
   [[['s1', 'ECON150', 0], ['s2', 'HIST140', 4]],
    [[3, 'pm'], [4, 'pm'], [5, 'am'], [5, 'eve'], [5, 'am'], [5, 'eve']],
    {'s1': ['sat', 'mon-eve', 'fri'], 's3': ['fri-pm', 'fri', 'sun-am']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'PHYS110', 2], ['s2', 'BIO130', 0], ['s2', 'ECON150', 3], ['s2', 'ECON150', 5]],
    [[3, 'am'], [2, 'pm'], [4, 'am'], [4, 'eve'], [4, 'eve'], [5, 'am']],
    {'s2': ['sun-am', 'fri-pm', 'fri'], 's3': ['sat', 'sun-am']}],
   [['s2', 'ECON150', 3]]),
  ('partial repair guard 2',
   [[['s1', 'MATH101H', 1], ['s3', 'MATH101', 0], ['s3', 'MATH101', 0], ['s2', 'PHYS110', 4],
     ['s2', 'BIO130', 1]],
    [[6, 'eve'], [5, 'am'], [5, 'eve'], [0, 'pm'], [5, 'am'], [0, 'pm']],
    {'s1': ['sat', 'mon-eve'], 's2': ['fri'], 's3': ['fri-pm', 'sun-am']}],
   [['s1', 'MATH101H', 1], ['s3', 'MATH101', 0], ['s3', 'MATH101', 0]]),
  ('boundary control 3', [[['s1', 'A', 0]], [[5, 'am']], {'s1': ['sat', 'fri-pm']}], [['s1', 'A', 0]]),
  ('normal control 4',
   [[['s3', 'ECON150', 3]], [[0, 'eve'], [4, 'eve'], [2, 'eve'], [0, 'am'], [4, 'pm'], [6, 'pm']],
    {'s1': ['fri-eve', 'sun-am'], 's2': ['fri', 'sat', 'fri-eve'], 's3': ['fri-eve', 'mon-eve', 'sat']}],
   []),
  ('normal control 5',
   [[['s3', 'BIO130', 0], ['s1', 'HIST140', 5]],
    [[2, 'pm'], [1, 'eve'], [1, 'eve'], [0, 'pm'], [0, 'am'], [0, 'eve']],
    {'s1': ['mon-eve', 'fri-pm'], 's2': ['fri-pm', 'sat'], 's3': ['fri-eve']}],
   [['s1', 'HIST140', 5]]),
  ('normal control 6',
   [[['s2', 'CHEM120', 0], ['s2', 'MATH101', 3], ['s1', 'HIST140', 2], ['s1', 'MATH101H', 1],
     ['s2', 'PHYS110', 1], ['s3', 'PHYS110', 3]],
    [[1, 'pm'], [4, 'pm'], [4, 'am'], [3, 'am'], [3, 'eve'], [3, 'eve']], {'s1': ['mon-eve']}],
   []),
  ('normal control 7',
   [[['s1', 'HIST140', 4]], [[4, 'eve'], [3, 'am'], [5, 'eve'], [6, 'pm'], [6, 'eve'], [6, 'pm']],
    {'s1': ['fri-pm', 'fri-eve', 'sun-am'], 's2': ['mon-eve', 'fri'], 's3': ['fri', 'fri-eve']}],
   [['s1', 'HIST140', 4]]),
  ('normal control 8',
   [[['s1', 'MATH101', 3], ['s3', 'BIO130', 1]],
    [[0, 'pm'], [2, 'pm'], [2, 'pm'], [4, 'pm'], [0, 'eve'], [5, 'eve']],
    {'s1': ['mon-eve'], 's2': ['fri', 'sat'], 's3': ['fri-pm', 'sun-am']}],
   [])],
 [('regression: one row per sitting 1',
   [[['s1', 'ECON150', 0], ['s2', 'ECON150', 3], ['s2', 'ECON150', 5]],
    [[4, 'am'], [4, 'eve'], [3, 'am'], [4, 'eve'], [0, 'pm'], [2, 'am']],
    {'s1': ['sun-am', 'fri-pm'], 's2': ['mon-eve', 'fri', 'fri-pm'], 's3': ['sat', 'sun-am']}],
   [['s2', 'ECON150', 3]]),
  ('regression variant: one row per sitting 2',
   [[['s2', 'MATH101H', 3], ['s1', 'CHEM120', 1], ['s1', 'CHEM120', 3], ['s2', 'MATH101', 0],
     ['s1', 'BIO130', 0], ['s3', 'MATH101', 1]],
    [[4, 'eve'], [3, 'pm'], [4, 'eve'], [1, 'am'], [3, 'pm'], [6, 'eve']],
    {'s1': ['fri-eve', 'sun-am', 'fri'], 's2': ['fri-eve'], 's3': ['fri-eve', 'mon-eve', 'fri-pm']}],
   [['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]),
  ('partial repair guard 3',
   [[['s3', 'ECON150', 0], ['s3', 'ECON150', 0]],
    [[4, 'pm'], [2, 'eve'], [6, 'am'], [6, 'am'], [5, 'eve'], [6, 'eve']],
    {'s1': ['sun-am', 'fri'], 's2': ['fri-eve', 'fri'], 's3': ['fri-pm']}],
   [['s3', 'ECON150', 0], ['s3', 'ECON150', 0]]),
  ('boundary control 4', [[['s1', 'A', 0]], [[4, 'eve']], {'s1': ['fri-pm']}], [['s1', 'A', 0]]),
  ('normal control 5',
   [[['s3', 'HIST140', 1], ['s3', 'PHYS110', 4], ['s2', 'CHEM120', 2], ['s2', 'MATH101H', 4],
     ['s2', 'CHEM120', 1]],
    [[2, 'pm'], [0, 'pm'], [4, 'eve'], [4, 'pm'], [4, 'pm'], [1, 'am']],
    {'s1': ['mon-eve'], 's3': ['mon-eve', 'fri-eve']}],
   []),
  ('normal control 6',
   [[['s1', 'CHEM120', 3], ['s1', 'BIO130', 4], ['s2', 'ECON150', 4], ['s1', 'HIST140', 0],
     ['s1', 'CHEM120', 1]],
    [[6, 'pm'], [3, 'pm'], [5, 'pm'], [0, 'eve'], [6, 'am'], [1, 'am']],
    {'s1': ['mon-eve', 'fri', 'sun-am'], 's2': ['sat', 'fri-pm', 'fri']}],
   [['s1', 'BIO130', 4], ['s1', 'CHEM120', 3], ['s1', 'HIST140', 0]]),
  ('normal control 7',
   [[['s3', 'CHEM120', 3], ['s2', 'MATH101', 0], ['s3', 'MATH101', 3], ['s3', 'ECON150', 0]],
    [[3, 'eve'], [3, 'pm'], [4, 'eve'], [0, 'am'], [0, 'pm'], [6, 'am']],
    {'s1': ['fri-eve', 'fri', 'sun-am'], 's3': ['fri-eve', 'sun-am', 'sat']}],
   []),
  ('normal control 8',
   [[['s3', 'HIST140', 4]], [[3, 'pm'], [5, 'pm'], [4, 'eve'], [1, 'eve'], [6, 'am'], [1, 'pm']],
    {'s1': ['fri-pm', 'fri-eve'], 's2': ['fri-eve', 'fri-pm'], 's3': ['mon-eve', 'sun-am']}],
   [['s3', 'HIST140', 4]])]]
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: one row per sitting 1[['s1', 'A', 0]][['s1', 'A', 0]]Passed
regression variant: one row per sitting 2[['s1', 'BIO130', 0], ['s2', 'MATH101', 0]][['s1', 'BIO130', 0], ['s2', 'MATH101', 0]]Passed
partial repair guard 3[['s3', 'ECON150', 0], ['s3', 'ECON150', 0]][['s3', 'ECON150', 0], ['s3', 'ECON150', 0]]Passed
normal control 4[][]Passed
normal control 5[][]Passed
normal control 6[['s1', 'CHEM120', 4]][['s1', 'CHEM120', 4]]Passed
normal control 7[][]Passed
normal control 8[][]Passed

SHA-256 / 8d5dd737802c91b47e19dcafee9c454c70b5092702bd3f35bd1087af79f47146

Verification & scope

Stipulated toy exam-timetabling rule set for a bounded model; it does not claim conformance with any institution's regulations or a benchmark specification, and it performs no search or optimisation. 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:52:07.121338+00:00.

Case digest / d5d784c0ad2a146c027384ecf4e0c5712cb13b1433239f66ac48ab94617cdc14