FA-95031 / Warehouse slotting and bin packing / Open access
Hazmat audit: SKU flagged against itself · case 01
A SKU stored in two slots is reported as incompatible with itself.
ROOT CAUSE
The pair loop does not skip two placements of the same SKU.
VERIFIED REPAIR
Skip pairs whose SKU codes are identical.
Unsuccessful approach: Skipping pairs of the same class hides genuine same-class rules such as organic peroxide spacing.
Case contract
placements [[sku, hazard class, aisle, bay]]; rules [[class_a, class_b, min_bay_gap]] apply in either order within the same aisle. A rule class matches a hazard class equal to it or a division of it ("4" matches "4.1"). A pair violates when |bay difference| < min_gap. Different SKUs only. Return sorted unique [sku_low, sku_high] pairs.
Why this case matters
Dangerous goods storage requires separation between incompatible hazard classes.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(placements, rules):
def matches(cls, rule):
return cls == rule or cls.startswith(rule + '.')
found = set()
n = len(placements)
for i in range(n):
for j in range(i + 1, n):
sa, ca, aa, ba = placements[i]
sb, cb, ab, bb = placements[j]
if aa != ab:
continue
gap = abs(ba - bb)
for ra, rb, min_gap in rules:
hit = (matches(ca, ra) and matches(cb, rb)) or (matches(ca, rb) and matches(cb, ra))
if hit and gap < min_gap:
found.add(tuple(sorted([sa, sb])))
return [list(p) for p in sorted(found)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 52', [[['H0', '5.2', 1, 1], ['H1', '8', 1, 5], ['H2', '5.2', 1, 1], ['H3', '5.1', 1, 6], ['H0', '5.2', 1, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['H0', 'H2']]], ['adjacent oxidizer', [[['F', '3', 1, 4], ['O', '5.1', 1, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['F', 'O']]], ['division match', [[['W', '4.3', 2, 2], ['C', '8', 2, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['C', 'W']]], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 6', [[['H0', '2.1', 1, 4], ['H1', '9', 1, 1]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['other aisle', [[['F', '3', 1, 4], ['O', '5.1', 2, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 9', [[['H0', '9', 1, 6], ['H1', '5.1', 1, 6], ['H2', '4.1', 1, 6], ['H3', '4.1', 1, 2], ['H4', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 17', [[['H0', '8', 1, 5], ['H1', '9', 2, 6], ['H2', '4.3', 1, 3], ['H3', '4.1', 1, 1], ['H4', '9', 1, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 25', [[['H0', '4.3', 1, 6], ['H1', '8', 2, 5], ['H2', '4.1', 1, 6], ['H3', '5.1', 2, 2], ['H0', '4.3', 1, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 52', [[['H0', '5.2', 1, 1], ['H1', '8', 1, 5], ['H2', '5.2', 1, 1], ['H3', '5.1', 1, 6], ['H0', '5.2', 1, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['H0', 'H2']]], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['other aisle', [[['F', '3', 1, 4], ['O', '5.1', 2, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['reverse order', [[['O', '5.1', 1, 1], ['G', '2.1', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['G', 'O']]], ['generated mix 20', [[['H0', '8', 1, 5], ['H1', '5.2', 2, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 28', [[['H0', '4.3', 2, 3], ['H1', '5.1', 1, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['other aisle', [[['F', '3', 1, 4], ['O', '5.1', 2, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 31', [[['H0', '3', 1, 6], ['H1', '4.1', 2, 4], ['H2', '2.1', 2, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 39', [[['H0', '8', 1, 2], ['H1', '8', 2, 5], ['H2', '3', 1, 1], ['H3', '4.3', 2, 3], ['H0', '8', 1, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 47', [[['H0', '5.2', 2, 2], ['H1', '3', 1, 2], ['H2', '4.1', 1, 3], ['H3', '5.2', 1, 5], ['H0', '5.2', 2, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 52', [[['H0', '5.2', 1, 1], ['H1', '8', 1, 5], ['H2', '5.2', 1, 1], ['H3', '5.1', 1, 6], ['H0', '5.2', 1, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['H0', 'H2']]], ['reverse order', [[['O', '5.1', 1, 1], ['G', '2.1', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['G', 'O']]], ['adjacent oxidizer', [[['F', '3', 1, 4], ['O', '5.1', 1, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['F', 'O']]], ['division match', [[['W', '4.3', 2, 2], ['C', '8', 2, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['C', 'W']]], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['generated mix 42', [[['H0', '8', 2, 1], ['H1', '3', 2, 6], ['H2', '3', 1, 5], ['H3', '5.2', 2, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 50', [[['H0', '8', 1, 2], ['H1', '2.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| same sku twice | [['P', 'P']] | [] | Failed |
| generated mix 52 | [['H0', 'H2']] | [['H0', 'H2']] | Passed |
| adjacent oxidizer | [['F', 'O']] | [['F', 'O']] | Passed |
| division match | [['C', 'W']] | [['C', 'W']] | Passed |
| same class rule | [['P', 'Q']] | [['P', 'Q']] | Passed |
| two pairs | [['A', 'Z'], ['B', 'C']] | [['A', 'Z'], ['B', 'C']] | Passed |
| gap equal ok | [] | [] | Passed |
| generated mix 6 | [] | [] | Passed |
SHA-256 / b9e721180aa6b351f6066f4315b1e319e3a2b4f1260a3c4f86e8f1dcf753a57e
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(placements, rules):
def matches(cls, rule):
return cls == rule or cls.startswith(rule + '.')
found = set()
n = len(placements)
for i in range(n):
for j in range(i + 1, n):
sa, ca, aa, ba = placements[i]
sb, cb, ab, bb = placements[j]
if ca == cb or aa != ab:
continue
gap = abs(ba - bb)
for ra, rb, min_gap in rules:
hit = (matches(ca, ra) and matches(cb, rb)) or (matches(ca, rb) and matches(cb, ra))
if hit and gap < min_gap:
found.add(tuple(sorted([sa, sb])))
return [list(p) for p in sorted(found)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 52', [[['H0', '5.2', 1, 1], ['H1', '8', 1, 5], ['H2', '5.2', 1, 1], ['H3', '5.1', 1, 6], ['H0', '5.2', 1, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['H0', 'H2']]], ['adjacent oxidizer', [[['F', '3', 1, 4], ['O', '5.1', 1, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['F', 'O']]], ['division match', [[['W', '4.3', 2, 2], ['C', '8', 2, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['C', 'W']]], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 6', [[['H0', '2.1', 1, 4], ['H1', '9', 1, 1]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['other aisle', [[['F', '3', 1, 4], ['O', '5.1', 2, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 9', [[['H0', '9', 1, 6], ['H1', '5.1', 1, 6], ['H2', '4.1', 1, 6], ['H3', '4.1', 1, 2], ['H4', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 17', [[['H0', '8', 1, 5], ['H1', '9', 2, 6], ['H2', '4.3', 1, 3], ['H3', '4.1', 1, 1], ['H4', '9', 1, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 25', [[['H0', '4.3', 1, 6], ['H1', '8', 2, 5], ['H2', '4.1', 1, 6], ['H3', '5.1', 2, 2], ['H0', '4.3', 1, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 52', [[['H0', '5.2', 1, 1], ['H1', '8', 1, 5], ['H2', '5.2', 1, 1], ['H3', '5.1', 1, 6], ['H0', '5.2', 1, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['H0', 'H2']]], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['other aisle', [[['F', '3', 1, 4], ['O', '5.1', 2, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['reverse order', [[['O', '5.1', 1, 1], ['G', '2.1', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['G', 'O']]], ['generated mix 20', [[['H0', '8', 1, 5], ['H1', '5.2', 2, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 28', [[['H0', '4.3', 2, 3], ['H1', '5.1', 1, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['other aisle', [[['F', '3', 1, 4], ['O', '5.1', 2, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 31', [[['H0', '3', 1, 6], ['H1', '4.1', 2, 4], ['H2', '2.1', 2, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 39', [[['H0', '8', 1, 2], ['H1', '8', 2, 5], ['H2', '3', 1, 1], ['H3', '4.3', 2, 3], ['H0', '8', 1, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 47', [[['H0', '5.2', 2, 2], ['H1', '3', 1, 2], ['H2', '4.1', 1, 3], ['H3', '5.2', 1, 5], ['H0', '5.2', 2, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 52', [[['H0', '5.2', 1, 1], ['H1', '8', 1, 5], ['H2', '5.2', 1, 1], ['H3', '5.1', 1, 6], ['H0', '5.2', 1, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['H0', 'H2']]], ['reverse order', [[['O', '5.1', 1, 1], ['G', '2.1', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['G', 'O']]], ['adjacent oxidizer', [[['F', '3', 1, 4], ['O', '5.1', 1, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['F', 'O']]], ['division match', [[['W', '4.3', 2, 2], ['C', '8', 2, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['C', 'W']]], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['generated mix 42', [[['H0', '8', 2, 1], ['H1', '3', 2, 6], ['H2', '3', 1, 5], ['H3', '5.2', 2, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 50', [[['H0', '8', 1, 2], ['H1', '2.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| same sku twice | [] | [] | Passed |
| generated mix 52 | [] | [['H0', 'H2']] | Failed |
| adjacent oxidizer | [['F', 'O']] | [['F', 'O']] | Passed |
| division match | [['C', 'W']] | [['C', 'W']] | Passed |
| same class rule | [] | [['P', 'Q']] | Failed |
| two pairs | [['A', 'Z'], ['B', 'C']] | [['A', 'Z'], ['B', 'C']] | Passed |
| gap equal ok | [] | [] | Passed |
| generated mix 6 | [] | [] | Passed |
SHA-256 / a391b3f225ec4a895a8abac5ba12d34062b02b9f98bdd689f1a36c33ab7f09f0
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(placements, rules):
def matches(cls, rule):
return cls == rule or cls.startswith(rule + '.')
found = set()
n = len(placements)
for i in range(n):
for j in range(i + 1, n):
sa, ca, aa, ba = placements[i]
sb, cb, ab, bb = placements[j]
if sa == sb or aa != ab:
continue
gap = abs(ba - bb)
for ra, rb, min_gap in rules:
hit = (matches(ca, ra) and matches(cb, rb)) or (matches(ca, rb) and matches(cb, ra))
if hit and gap < min_gap:
found.add(tuple(sorted([sa, sb])))
return [list(p) for p in sorted(found)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 52', [[['H0', '5.2', 1, 1], ['H1', '8', 1, 5], ['H2', '5.2', 1, 1], ['H3', '5.1', 1, 6], ['H0', '5.2', 1, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['H0', 'H2']]], ['adjacent oxidizer', [[['F', '3', 1, 4], ['O', '5.1', 1, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['F', 'O']]], ['division match', [[['W', '4.3', 2, 2], ['C', '8', 2, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['C', 'W']]], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 6', [[['H0', '2.1', 1, 4], ['H1', '9', 1, 1]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['other aisle', [[['F', '3', 1, 4], ['O', '5.1', 2, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 9', [[['H0', '9', 1, 6], ['H1', '5.1', 1, 6], ['H2', '4.1', 1, 6], ['H3', '4.1', 1, 2], ['H4', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 17', [[['H0', '8', 1, 5], ['H1', '9', 2, 6], ['H2', '4.3', 1, 3], ['H3', '4.1', 1, 1], ['H4', '9', 1, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 25', [[['H0', '4.3', 1, 6], ['H1', '8', 2, 5], ['H2', '4.1', 1, 6], ['H3', '5.1', 2, 2], ['H0', '4.3', 1, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 52', [[['H0', '5.2', 1, 1], ['H1', '8', 1, 5], ['H2', '5.2', 1, 1], ['H3', '5.1', 1, 6], ['H0', '5.2', 1, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['H0', 'H2']]], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['other aisle', [[['F', '3', 1, 4], ['O', '5.1', 2, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['reverse order', [[['O', '5.1', 1, 1], ['G', '2.1', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['G', 'O']]], ['generated mix 20', [[['H0', '8', 1, 5], ['H1', '5.2', 2, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 28', [[['H0', '4.3', 2, 3], ['H1', '5.1', 1, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['other aisle', [[['F', '3', 1, 4], ['O', '5.1', 2, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['two pairs', [[['A', '3', 1, 1], ['Z', '5.1', 1, 2], ['B', '3', 1, 5], ['C', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['A', 'Z'], ['B', 'C']]], ['gap equal ok', [[['F', '3', 1, 4], ['O', '5.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 31', [[['H0', '3', 1, 6], ['H1', '4.1', 2, 4], ['H2', '2.1', 2, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 39', [[['H0', '8', 1, 2], ['H1', '8', 2, 5], ['H2', '3', 1, 1], ['H3', '4.3', 2, 3], ['H0', '8', 1, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 47', [[['H0', '5.2', 2, 2], ['H1', '3', 1, 2], ['H2', '4.1', 1, 3], ['H3', '5.2', 1, 5], ['H0', '5.2', 2, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]], [['same sku twice', [[['P', '5.2', 1, 3], ['P', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 52', [[['H0', '5.2', 1, 1], ['H1', '8', 1, 5], ['H2', '5.2', 1, 1], ['H3', '5.1', 1, 6], ['H0', '5.2', 1, 4]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['H0', 'H2']]], ['reverse order', [[['O', '5.1', 1, 1], ['G', '2.1', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['G', 'O']]], ['adjacent oxidizer', [[['F', '3', 1, 4], ['O', '5.1', 1, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['F', 'O']]], ['division match', [[['W', '4.3', 2, 2], ['C', '8', 2, 2]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['C', 'W']]], ['same class rule', [[['P', '5.2', 1, 3], ['Q', '5.2', 1, 3]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], [['P', 'Q']]], ['generated mix 42', [[['H0', '8', 2, 1], ['H1', '3', 2, 6], ['H2', '3', 1, 5], ['H3', '5.2', 2, 5]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []], ['generated mix 50', [[['H0', '8', 1, 2], ['H1', '2.1', 1, 6]], [['3', '5.1', 2], ['4', '8', 1], ['5.2', '5.2', 1], ['2.1', '5', 3]]], []]]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| same sku twice | [] | [] | Passed |
| generated mix 52 | [['H0', 'H2']] | [['H0', 'H2']] | Passed |
| adjacent oxidizer | [['F', 'O']] | [['F', 'O']] | Passed |
| division match | [['C', 'W']] | [['C', 'W']] | Passed |
| same class rule | [['P', 'Q']] | [['P', 'Q']] | Passed |
| two pairs | [['A', 'Z'], ['B', 'C']] | [['A', 'Z'], ['B', 'C']] | Passed |
| gap equal ok | [] | [] | Passed |
| generated mix 6 | [] | [] | Passed |
SHA-256 / 22a3cc601d9567a7b80319ca971abb075a71cc9416ac7af21f6c6f31acdda9e9
Verification & scope
Stipulated bay-gap rule table; not a regulatory segregation chart. 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:09.925955+00:00.
Case digest / f744af60684c0e817f53d36e30db20d1b14136ac0450b9bee50ce2a5d127efaa