FAILURE MAP
← Case archive

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.

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

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 fixtureActualExpectedOutcome
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 fixtureActualExpectedOutcome
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 fixtureActualExpectedOutcome
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