FAILURE MAP
← Case archive

FA-94791 / Exam timetabling constraints / Open access

Next-morning check looks at the same slot next day · case 01

An evening exam followed by the next day's first exam is not reported.

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

ROOT CAUSE

The following morning is computed as p + spd.

VERIFIED REPAIR

The next morning is period p + 1.

Unsuccessful approach: Also accepting p + 2 reports evening-then-midday sequences.

Case contract

sits [student, period] with spd periods per day (day = p // spd). Report ["day", student, day] when a student has more than maxday distinct periods on a day, and ["eve_morn", student, day] when a student sits the last period of a day and the first period of the next day. Rows by student: day findings by day, then evening-morning findings.

Why this case matters

Daily exam limits and evening-then-morning sequences are common student-welfare rules.

1 / The failure

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

N = 1
observations = []
def solve(sits, spd, maxday):
    by = {}
    for st, p in sits:
        by.setdefault(st, set()).add(p)
    out = []
    for st in sorted(by):
        ps = by[st]
        days = {}
        for p in ps:
            days[p // spd] = days.get(p // spd, 0) + 1
        for d in sorted(days):
            if days[d] > maxday:
                out.append(['day', st, d])
        for p in sorted(ps):
            if p % spd == spd - 1 and p + spd in ps:
                out.append(['eve_morn', st, p // spd])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: next morning period 1', [[['s1', 2], ['s1', 3]], 3, 2], [['eve_morn', 's1', 0]]),
  ('regression variant: next morning period 2',
   [[['s2', 8], ['s3', 2], ['s2', 1], ['s2', 1], ['s3', 3]], 3, 1], [['eve_morn', 's3', 0]]),
  ('partial repair guard 3',
   [[['s1', 3], ['s3', 7], ['s3', 11], ['s3', 9], ['s2', 0], ['s1', 6], ['s3', 7], ['s1', 6]], 4, 2], []),
  ('boundary control 4', [[['s1', 0], ['s1', 1], ['s1', 2]], 3, 2], [['day', 's1', 0]]),
  ('normal control 5', [[['s2', 3], ['s1', 6]], 3, 2], []),
  ('normal control 6', [[['s1', 3], ['s3', 2], ['s3', 2]], 4, 1], []),
  ('normal control 7', [[['s3', 2], ['s1', 4], ['s3', 11], ['s1', 3], ['s1', 11]], 4, 2],
   [['eve_morn', 's1', 0]]),
  ('normal control 8', [[['s3', 0], ['s3', 0], ['s1', 1], ['s3', 3], ['s1', 0]], 2, 2], [])],
 [('regression: next morning period 1', [[['s1', 5], ['s1', 6]], 3, 2], [['eve_morn', 's1', 1]]),
  ('regression variant: next morning period 2',
   [[['s1', 7], ['s3', 8], ['s1', 9], ['s1', 11], ['s1', 4], ['s3', 6], ['s3', 7]], 4, 1],
   [['day', 's1', 1], ['day', 's1', 2], ['day', 's3', 1], ['eve_morn', 's3', 1]]),
  ('partial repair guard 3',
   [[['s2', 4], ['s2', 9], ['s1', 10], ['s1', 10], ['s2', 11], ['s2', 1], ['s2', 7], ['s3', 7]], 4, 1],
   [['day', 's2', 1], ['day', 's2', 2]]),
  ('boundary control 4', [[['s1', 1], ['s1', 2]], 3, 2], []),
  ('normal control 5', [[['s3', 2], ['s2', 2], ['s1', 6], ['s2', 4], ['s2', 4], ['s2', 8], ['s1', 2]], 3, 1],
   []),
  ('normal control 6', [[['s3', 5], ['s3', 5]], 3, 2], []),
  ('normal control 7', [[['s2', 2], ['s1', 8], ['s3', 1], ['s3', 5], ['s2', 0], ['s1', 1]], 3, 1],
   [['day', 's2', 0]]),
  ('normal control 8', [[['s1', 1], ['s2', 1], ['s2', 2], ['s1', 1], ['s3', 8]], 3, 1], [['day', 's2', 0]])],
 [('regression: next morning period 1', [[['s3', 3], ['s1', 1], ['s2', 7], ['s3', 5], ['s3', 8]], 3, 1],
   [['day', 's3', 1]]),
  ('regression variant: next morning period 2', [[['s2', 3], ['s1', 4], ['s2', 4]], 2, 2],
   [['eve_morn', 's2', 1]]),
  ('partial repair guard 3', [[['s2', 4], ['s1', 1], ['s2', 5], ['s2', 7]], 3, 1], [['day', 's2', 1]]),
  ('boundary control 4', [[['s1', 5], ['s1', 6]], 3, 2], [['eve_morn', 's1', 1]]),
  ('normal control 5', [[['s1', 0], ['s1', 6], ['s1', 0], ['s2', 5], ['s2', 5], ['s3', 0]], 4, 1], []),
  ('normal control 6', [[['s2', 3], ['s3', 4], ['s3', 0], ['s2', 3], ['s2', 2]], 2, 1], [['day', 's2', 1]]),
  ('normal control 7', [[['s3', 1], ['s3', 5]], 3, 2], []),
  ('normal control 8',
   [[['s2', 3], ['s3', 5], ['s3', 2], ['s3', 0], ['s2', 1], ['s1', 2], ['s3', 1], ['s3', 4]], 2, 2],
   [['eve_morn', 's3', 0]])],
 [('regression: next morning period 1',
   [[['s1', 5], ['s3', 2], ['s1', 5], ['s2', 5], ['s1', 3], ['s1', 1], ['s1', 4]], 2, 1],
   [['day', 's1', 2], ['eve_morn', 's1', 1]]),
  ('regression variant: next morning period 2', [[['s1', 3], ['s3', 2], ['s1', 1], ['s3', 2]], 2, 2], []),
  ('partial repair guard 3',
   [[['s1', 1], ['s3', 3], ['s1', 4], ['s3', 6], ['s1', 8], ['s2', 5], ['s1', 2], ['s3', 0]], 3, 2], []),
  ('boundary control 4', [[['s1', 0], ['s1', 1]], 3, 2], []),
  ('normal control 5', [[['s3', 0], ['s2', 1], ['s1', 3], ['s2', 5], ['s3', 1], ['s3', 3]], 2, 1],
   [['day', 's3', 0]]),
  ('normal control 6', [[['s3', 4], ['s2', 5], ['s3', 6], ['s3', 5], ['s2', 0], ['s3', 4], ['s1', 0]], 3, 2],
   [['eve_morn', 's3', 1]]),
  ('normal control 7', [[['s1', 1], ['s1', 2]], 4, 1], [['day', 's1', 0]]),
  ('normal control 8', [[['s3', 4], ['s2', 8], ['s3', 1], ['s1', 1], ['s2', 3]], 3, 1], [])],
 [('regression: next morning period 1',
   [[['s3', 1], ['s2', 4], ['s1', 11], ['s1', 7], ['s2', 1], ['s2', 5], ['s3', 2], ['s3', 4]], 4, 1],
   [['day', 's2', 1], ['day', 's3', 0]]),
  ('regression variant: next morning period 2',
   [[['s1', 2], ['s2', 6], ['s3', 4], ['s3', 4], ['s1', 5], ['s3', 8], ['s3', 2], ['s1', 6]], 3, 2],
   [['eve_morn', 's1', 1]]),
  ('partial repair guard 3',
   [[['s2', 0], ['s3', 2], ['s1', 3], ['s2', 3], ['s2', 5], ['s3', 0], ['s1', 4], ['s3', 0]], 2, 2],
   [['eve_morn', 's1', 1]]),
  ('boundary control 4', [[['s1', 2], ['s1', 3]], 3, 2], [['eve_morn', 's1', 0]]),
  ('normal control 5',
   [[['s2', 5], ['s2', 1], ['s1', 2], ['s2', 3], ['s1', 4], ['s2', 1], ['s3', 2], ['s2', 0]], 2, 1],
   [['day', 's2', 0]]),
  ('normal control 6', [[['s1', 3], ['s3', 2], ['s1', 3]], 3, 1], []),
  ('normal control 7', [[['s1', 4], ['s1', 0], ['s1', 3], ['s1', 0], ['s1', 2], ['s3', 4], ['s2', 2]], 2, 1],
   [['day', 's1', 1], ['eve_morn', 's1', 1]]),
  ('normal control 8', [[['s1', 3], ['s3', 2], ['s1', 1], ['s3', 2]], 2, 2], [])]]
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: next morning period 1[][['eve_morn', 's1', 0]]Failed
regression variant: next morning period 2[][['eve_morn', 's3', 0]]Failed
partial repair guard 3[['eve_morn', 's3', 1]][]Failed
boundary control 4[['day', 's1', 0]][['day', 's1', 0]]Passed
normal control 5[][]Passed
normal control 6[][]Passed
normal control 7[][['eve_morn', 's1', 0]]Failed
normal control 8[][]Passed

SHA-256 / 1767dceb7f74dced61a0e2e615aeecced7042686322a5e398d8b18f029f07fd5

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(sits, spd, maxday):
    by = {}
    for st, p in sits:
        by.setdefault(st, set()).add(p)
    out = []
    for st in sorted(by):
        ps = by[st]
        days = {}
        for p in ps:
            days[p // spd] = days.get(p // spd, 0) + 1
        for d in sorted(days):
            if days[d] > maxday:
                out.append(['day', st, d])
        for p in sorted(ps):
            if p % spd == spd - 1 and (p + 1 in ps or p + 2 in ps):
                out.append(['eve_morn', st, p // spd])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: next morning period 1', [[['s1', 2], ['s1', 3]], 3, 2], [['eve_morn', 's1', 0]]),
  ('regression variant: next morning period 2',
   [[['s2', 8], ['s3', 2], ['s2', 1], ['s2', 1], ['s3', 3]], 3, 1], [['eve_morn', 's3', 0]]),
  ('partial repair guard 3',
   [[['s1', 3], ['s3', 7], ['s3', 11], ['s3', 9], ['s2', 0], ['s1', 6], ['s3', 7], ['s1', 6]], 4, 2], []),
  ('boundary control 4', [[['s1', 0], ['s1', 1], ['s1', 2]], 3, 2], [['day', 's1', 0]]),
  ('normal control 5', [[['s2', 3], ['s1', 6]], 3, 2], []),
  ('normal control 6', [[['s1', 3], ['s3', 2], ['s3', 2]], 4, 1], []),
  ('normal control 7', [[['s3', 2], ['s1', 4], ['s3', 11], ['s1', 3], ['s1', 11]], 4, 2],
   [['eve_morn', 's1', 0]]),
  ('normal control 8', [[['s3', 0], ['s3', 0], ['s1', 1], ['s3', 3], ['s1', 0]], 2, 2], [])],
 [('regression: next morning period 1', [[['s1', 5], ['s1', 6]], 3, 2], [['eve_morn', 's1', 1]]),
  ('regression variant: next morning period 2',
   [[['s1', 7], ['s3', 8], ['s1', 9], ['s1', 11], ['s1', 4], ['s3', 6], ['s3', 7]], 4, 1],
   [['day', 's1', 1], ['day', 's1', 2], ['day', 's3', 1], ['eve_morn', 's3', 1]]),
  ('partial repair guard 3',
   [[['s2', 4], ['s2', 9], ['s1', 10], ['s1', 10], ['s2', 11], ['s2', 1], ['s2', 7], ['s3', 7]], 4, 1],
   [['day', 's2', 1], ['day', 's2', 2]]),
  ('boundary control 4', [[['s1', 1], ['s1', 2]], 3, 2], []),
  ('normal control 5', [[['s3', 2], ['s2', 2], ['s1', 6], ['s2', 4], ['s2', 4], ['s2', 8], ['s1', 2]], 3, 1],
   []),
  ('normal control 6', [[['s3', 5], ['s3', 5]], 3, 2], []),
  ('normal control 7', [[['s2', 2], ['s1', 8], ['s3', 1], ['s3', 5], ['s2', 0], ['s1', 1]], 3, 1],
   [['day', 's2', 0]]),
  ('normal control 8', [[['s1', 1], ['s2', 1], ['s2', 2], ['s1', 1], ['s3', 8]], 3, 1], [['day', 's2', 0]])],
 [('regression: next morning period 1', [[['s3', 3], ['s1', 1], ['s2', 7], ['s3', 5], ['s3', 8]], 3, 1],
   [['day', 's3', 1]]),
  ('regression variant: next morning period 2', [[['s2', 3], ['s1', 4], ['s2', 4]], 2, 2],
   [['eve_morn', 's2', 1]]),
  ('partial repair guard 3', [[['s2', 4], ['s1', 1], ['s2', 5], ['s2', 7]], 3, 1], [['day', 's2', 1]]),
  ('boundary control 4', [[['s1', 5], ['s1', 6]], 3, 2], [['eve_morn', 's1', 1]]),
  ('normal control 5', [[['s1', 0], ['s1', 6], ['s1', 0], ['s2', 5], ['s2', 5], ['s3', 0]], 4, 1], []),
  ('normal control 6', [[['s2', 3], ['s3', 4], ['s3', 0], ['s2', 3], ['s2', 2]], 2, 1], [['day', 's2', 1]]),
  ('normal control 7', [[['s3', 1], ['s3', 5]], 3, 2], []),
  ('normal control 8',
   [[['s2', 3], ['s3', 5], ['s3', 2], ['s3', 0], ['s2', 1], ['s1', 2], ['s3', 1], ['s3', 4]], 2, 2],
   [['eve_morn', 's3', 0]])],
 [('regression: next morning period 1',
   [[['s1', 5], ['s3', 2], ['s1', 5], ['s2', 5], ['s1', 3], ['s1', 1], ['s1', 4]], 2, 1],
   [['day', 's1', 2], ['eve_morn', 's1', 1]]),
  ('regression variant: next morning period 2', [[['s1', 3], ['s3', 2], ['s1', 1], ['s3', 2]], 2, 2], []),
  ('partial repair guard 3',
   [[['s1', 1], ['s3', 3], ['s1', 4], ['s3', 6], ['s1', 8], ['s2', 5], ['s1', 2], ['s3', 0]], 3, 2], []),
  ('boundary control 4', [[['s1', 0], ['s1', 1]], 3, 2], []),
  ('normal control 5', [[['s3', 0], ['s2', 1], ['s1', 3], ['s2', 5], ['s3', 1], ['s3', 3]], 2, 1],
   [['day', 's3', 0]]),
  ('normal control 6', [[['s3', 4], ['s2', 5], ['s3', 6], ['s3', 5], ['s2', 0], ['s3', 4], ['s1', 0]], 3, 2],
   [['eve_morn', 's3', 1]]),
  ('normal control 7', [[['s1', 1], ['s1', 2]], 4, 1], [['day', 's1', 0]]),
  ('normal control 8', [[['s3', 4], ['s2', 8], ['s3', 1], ['s1', 1], ['s2', 3]], 3, 1], [])],
 [('regression: next morning period 1',
   [[['s3', 1], ['s2', 4], ['s1', 11], ['s1', 7], ['s2', 1], ['s2', 5], ['s3', 2], ['s3', 4]], 4, 1],
   [['day', 's2', 1], ['day', 's3', 0]]),
  ('regression variant: next morning period 2',
   [[['s1', 2], ['s2', 6], ['s3', 4], ['s3', 4], ['s1', 5], ['s3', 8], ['s3', 2], ['s1', 6]], 3, 2],
   [['eve_morn', 's1', 1]]),
  ('partial repair guard 3',
   [[['s2', 0], ['s3', 2], ['s1', 3], ['s2', 3], ['s2', 5], ['s3', 0], ['s1', 4], ['s3', 0]], 2, 2],
   [['eve_morn', 's1', 1]]),
  ('boundary control 4', [[['s1', 2], ['s1', 3]], 3, 2], [['eve_morn', 's1', 0]]),
  ('normal control 5',
   [[['s2', 5], ['s2', 1], ['s1', 2], ['s2', 3], ['s1', 4], ['s2', 1], ['s3', 2], ['s2', 0]], 2, 1],
   [['day', 's2', 0]]),
  ('normal control 6', [[['s1', 3], ['s3', 2], ['s1', 3]], 3, 1], []),
  ('normal control 7', [[['s1', 4], ['s1', 0], ['s1', 3], ['s1', 0], ['s1', 2], ['s3', 4], ['s2', 2]], 2, 1],
   [['day', 's1', 1], ['eve_morn', 's1', 1]]),
  ('normal control 8', [[['s1', 3], ['s3', 2], ['s1', 1], ['s3', 2]], 2, 2], [])]]
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: next morning period 1[['eve_morn', 's1', 0]][['eve_morn', 's1', 0]]Passed
regression variant: next morning period 2[['eve_morn', 's3', 0]][['eve_morn', 's3', 0]]Passed
partial repair guard 3[['eve_morn', 's3', 1]][]Failed
boundary control 4[['day', 's1', 0]][['day', 's1', 0]]Passed
normal control 5[][]Passed
normal control 6[][]Passed
normal control 7[['eve_morn', 's1', 0]][['eve_morn', 's1', 0]]Passed
normal control 8[][]Passed

SHA-256 / 65938d1b71bbbc395908f9ab2621fe90ad1eedb29e9a506d0dea49b81f5c04c0

3 / The verified repair

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

N = 1
observations = []
def solve(sits, spd, maxday):
    by = {}
    for st, p in sits:
        by.setdefault(st, set()).add(p)
    out = []
    for st in sorted(by):
        ps = by[st]
        days = {}
        for p in ps:
            days[p // spd] = days.get(p // spd, 0) + 1
        for d in sorted(days):
            if days[d] > maxday:
                out.append(['day', st, d])
        for p in sorted(ps):
            if p % spd == spd - 1 and p + 1 in ps:
                out.append(['eve_morn', st, p // spd])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: next morning period 1', [[['s1', 2], ['s1', 3]], 3, 2], [['eve_morn', 's1', 0]]),
  ('regression variant: next morning period 2',
   [[['s2', 8], ['s3', 2], ['s2', 1], ['s2', 1], ['s3', 3]], 3, 1], [['eve_morn', 's3', 0]]),
  ('partial repair guard 3',
   [[['s1', 3], ['s3', 7], ['s3', 11], ['s3', 9], ['s2', 0], ['s1', 6], ['s3', 7], ['s1', 6]], 4, 2], []),
  ('boundary control 4', [[['s1', 0], ['s1', 1], ['s1', 2]], 3, 2], [['day', 's1', 0]]),
  ('normal control 5', [[['s2', 3], ['s1', 6]], 3, 2], []),
  ('normal control 6', [[['s1', 3], ['s3', 2], ['s3', 2]], 4, 1], []),
  ('normal control 7', [[['s3', 2], ['s1', 4], ['s3', 11], ['s1', 3], ['s1', 11]], 4, 2],
   [['eve_morn', 's1', 0]]),
  ('normal control 8', [[['s3', 0], ['s3', 0], ['s1', 1], ['s3', 3], ['s1', 0]], 2, 2], [])],
 [('regression: next morning period 1', [[['s1', 5], ['s1', 6]], 3, 2], [['eve_morn', 's1', 1]]),
  ('regression variant: next morning period 2',
   [[['s1', 7], ['s3', 8], ['s1', 9], ['s1', 11], ['s1', 4], ['s3', 6], ['s3', 7]], 4, 1],
   [['day', 's1', 1], ['day', 's1', 2], ['day', 's3', 1], ['eve_morn', 's3', 1]]),
  ('partial repair guard 3',
   [[['s2', 4], ['s2', 9], ['s1', 10], ['s1', 10], ['s2', 11], ['s2', 1], ['s2', 7], ['s3', 7]], 4, 1],
   [['day', 's2', 1], ['day', 's2', 2]]),
  ('boundary control 4', [[['s1', 1], ['s1', 2]], 3, 2], []),
  ('normal control 5', [[['s3', 2], ['s2', 2], ['s1', 6], ['s2', 4], ['s2', 4], ['s2', 8], ['s1', 2]], 3, 1],
   []),
  ('normal control 6', [[['s3', 5], ['s3', 5]], 3, 2], []),
  ('normal control 7', [[['s2', 2], ['s1', 8], ['s3', 1], ['s3', 5], ['s2', 0], ['s1', 1]], 3, 1],
   [['day', 's2', 0]]),
  ('normal control 8', [[['s1', 1], ['s2', 1], ['s2', 2], ['s1', 1], ['s3', 8]], 3, 1], [['day', 's2', 0]])],
 [('regression: next morning period 1', [[['s3', 3], ['s1', 1], ['s2', 7], ['s3', 5], ['s3', 8]], 3, 1],
   [['day', 's3', 1]]),
  ('regression variant: next morning period 2', [[['s2', 3], ['s1', 4], ['s2', 4]], 2, 2],
   [['eve_morn', 's2', 1]]),
  ('partial repair guard 3', [[['s2', 4], ['s1', 1], ['s2', 5], ['s2', 7]], 3, 1], [['day', 's2', 1]]),
  ('boundary control 4', [[['s1', 5], ['s1', 6]], 3, 2], [['eve_morn', 's1', 1]]),
  ('normal control 5', [[['s1', 0], ['s1', 6], ['s1', 0], ['s2', 5], ['s2', 5], ['s3', 0]], 4, 1], []),
  ('normal control 6', [[['s2', 3], ['s3', 4], ['s3', 0], ['s2', 3], ['s2', 2]], 2, 1], [['day', 's2', 1]]),
  ('normal control 7', [[['s3', 1], ['s3', 5]], 3, 2], []),
  ('normal control 8',
   [[['s2', 3], ['s3', 5], ['s3', 2], ['s3', 0], ['s2', 1], ['s1', 2], ['s3', 1], ['s3', 4]], 2, 2],
   [['eve_morn', 's3', 0]])],
 [('regression: next morning period 1',
   [[['s1', 5], ['s3', 2], ['s1', 5], ['s2', 5], ['s1', 3], ['s1', 1], ['s1', 4]], 2, 1],
   [['day', 's1', 2], ['eve_morn', 's1', 1]]),
  ('regression variant: next morning period 2', [[['s1', 3], ['s3', 2], ['s1', 1], ['s3', 2]], 2, 2], []),
  ('partial repair guard 3',
   [[['s1', 1], ['s3', 3], ['s1', 4], ['s3', 6], ['s1', 8], ['s2', 5], ['s1', 2], ['s3', 0]], 3, 2], []),
  ('boundary control 4', [[['s1', 0], ['s1', 1]], 3, 2], []),
  ('normal control 5', [[['s3', 0], ['s2', 1], ['s1', 3], ['s2', 5], ['s3', 1], ['s3', 3]], 2, 1],
   [['day', 's3', 0]]),
  ('normal control 6', [[['s3', 4], ['s2', 5], ['s3', 6], ['s3', 5], ['s2', 0], ['s3', 4], ['s1', 0]], 3, 2],
   [['eve_morn', 's3', 1]]),
  ('normal control 7', [[['s1', 1], ['s1', 2]], 4, 1], [['day', 's1', 0]]),
  ('normal control 8', [[['s3', 4], ['s2', 8], ['s3', 1], ['s1', 1], ['s2', 3]], 3, 1], [])],
 [('regression: next morning period 1',
   [[['s3', 1], ['s2', 4], ['s1', 11], ['s1', 7], ['s2', 1], ['s2', 5], ['s3', 2], ['s3', 4]], 4, 1],
   [['day', 's2', 1], ['day', 's3', 0]]),
  ('regression variant: next morning period 2',
   [[['s1', 2], ['s2', 6], ['s3', 4], ['s3', 4], ['s1', 5], ['s3', 8], ['s3', 2], ['s1', 6]], 3, 2],
   [['eve_morn', 's1', 1]]),
  ('partial repair guard 3',
   [[['s2', 0], ['s3', 2], ['s1', 3], ['s2', 3], ['s2', 5], ['s3', 0], ['s1', 4], ['s3', 0]], 2, 2],
   [['eve_morn', 's1', 1]]),
  ('boundary control 4', [[['s1', 2], ['s1', 3]], 3, 2], [['eve_morn', 's1', 0]]),
  ('normal control 5',
   [[['s2', 5], ['s2', 1], ['s1', 2], ['s2', 3], ['s1', 4], ['s2', 1], ['s3', 2], ['s2', 0]], 2, 1],
   [['day', 's2', 0]]),
  ('normal control 6', [[['s1', 3], ['s3', 2], ['s1', 3]], 3, 1], []),
  ('normal control 7', [[['s1', 4], ['s1', 0], ['s1', 3], ['s1', 0], ['s1', 2], ['s3', 4], ['s2', 2]], 2, 1],
   [['day', 's1', 1], ['eve_morn', 's1', 1]]),
  ('normal control 8', [[['s1', 3], ['s3', 2], ['s1', 1], ['s3', 2]], 2, 2], [])]]
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: next morning period 1[['eve_morn', 's1', 0]][['eve_morn', 's1', 0]]Passed
regression variant: next morning period 2[['eve_morn', 's3', 0]][['eve_morn', 's3', 0]]Passed
partial repair guard 3[][]Passed
boundary control 4[['day', 's1', 0]][['day', 's1', 0]]Passed
normal control 5[][]Passed
normal control 6[][]Passed
normal control 7[['eve_morn', 's1', 0]][['eve_morn', 's1', 0]]Passed
normal control 8[][]Passed

SHA-256 / 67a1232c20da6f8cb7c6896a94746dbd4e1e0c83114ead5003f68bca9c5d0611

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.789066+00:00.

Case digest / 893c8f90d86f3bede91cea3b2fdf586905dcb6c86490af02b079dd55b6ad86cd