FAILURE MAP
← Case archive

FA-94991 / Warehouse slotting and bin packing / Open access

Pallet build: base height not deducted · case 01

Built pallets exceed the rack opening height by up to the pallet base.

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

ROOT CAUSE

The layer count divides the full height limit by the case height without subtracting the pallet base.

VERIFIED REPAIR

Subtract the 15-unit base before dividing the height limit into layers.

Unsuccessful approach: Reserving an extra case height loses a legitimate top layer.

Case contract

case [l, w, h, kg], pallet [L, W]; cases stay upright but may rotate 90 degrees; all layers share one orientation. Pallet base adds 15 height and 25 kg tare. Cases per pallet are bounded by whole layers within max_h and by max_kg (a partial top layer is allowed). Return [per_layer, layers used, cases, height, weight].

Why this case matters

Pallet build limits govern reserve storage heights and floor loading.

1 / The failure

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

N = 1
observations = []
def solve(case, pallet, max_h, max_kg):
    l, w, h, kg = case
    L, W = pallet
    per_layer = max((L // l) * (W // w), (L // w) * (W // l))
    if per_layer == 0:
        return [0, 0, 0, 15, 25]
    layers = max_h // h
    by_weight = (max_kg - 25) // kg
    cases = min(per_layer * layers, by_weight)
    if cases <= 0:
        return [per_layer, 0, 0, 15, 25]
    full = -(-cases // per_layer)
    return [per_layer, full, cases, 15 + full * h, 25 + cases * kg]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['generated mix 2', [[30, 30, 30, 8], [120, 100], 100, 1200], [12, 2, 24, 75, 217]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['generated mix 7', [[40, 30, 20, 5], [120, 80], 140, 1025], [8, 6, 48, 135, 265]], ['generated mix 15', [[50, 20, 30, 8], [120, 80], 115, 800], [8, 3, 24, 105, 217]]], [['generated mix 23', [[25, 25, 25, 12], [120, 100], 100, 800], [16, 3, 48, 90, 601]], ['generated mix 7', [[40, 30, 20, 5], [120, 80], 140, 1025], [8, 6, 48, 135, 265]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['generated mix 10', [[30, 15, 20, 5], [120, 80], 190, 1025], [20, 8, 160, 175, 825]], ['generated mix 18', [[30, 25, 10, 2], [120, 100], 115, 1025], [16, 10, 160, 115, 345]]], [['generated mix 55', [[50, 30, 30, 5], [120, 100], 190, 1200], [8, 5, 40, 165, 225]], ['generated mix 12', [[40, 15, 30, 12], [120, 80], 140, 1200], [16, 4, 64, 135, 793]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['generated mix 21', [[25, 20, 30, 2], [120, 80], 140, 300], [18, 4, 72, 135, 169]], ['generated mix 29', [[50, 30, 30, 20], [120, 100], 190, 300], [8, 2, 13, 75, 285]]], [['generated mix 2', [[30, 30, 30, 8], [120, 100], 100, 1200], [12, 2, 24, 75, 217]], ['generated mix 17', [[30, 30, 30, 8], [120, 80], 165, 500], [8, 5, 40, 165, 345]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['generated mix 33', [[40, 30, 10, 20], [120, 80], 165, 800], [8, 5, 38, 65, 785]], ['generated mix 41', [[25, 25, 10, 20], [120, 100], 165, 1200], [16, 4, 58, 55, 1185]]], [['generated mix 23', [[25, 25, 25, 12], [120, 100], 100, 800], [16, 3, 48, 90, 601]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['generated mix 43', [[25, 20, 20, 12], [120, 100], 140, 1200], [24, 5, 97, 115, 1189]], ['generated mix 51', [[25, 15, 10, 8], [120, 80], 165, 500], [24, 3, 59, 45, 497]], ['generated mix 59', [[30, 15, 10, 20], [120, 80], 165, 500], [20, 2, 23, 35, 485]]]]
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
generated mix 2[12, 3, 36, 105, 313][12, 2, 24, 75, 217]Failed
rotation wins[8, 5, 40, 115, 225][8, 5, 40, 115, 225]Passed
listed orientation wins[20, 5, 100, 115, 525][20, 5, 100, 115, 525]Passed
weight bound partial layer[9, 3, 20, 90, 425][9, 3, 20, 90, 425]Passed
too heavy for one[9, 0, 0, 15, 25][9, 0, 0, 15, 25]Passed
height exact[9, 5, 45, 140, 115][9, 5, 45, 140, 115]Passed
generated mix 7[8, 7, 56, 155, 305][8, 6, 48, 135, 265]Failed
generated mix 15[8, 3, 24, 105, 217][8, 3, 24, 105, 217]Passed

SHA-256 / fdcdf383d31c308594bc0c132dd152f109b2a3007360e4221b5cfafc8daf50ee

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(case, pallet, max_h, max_kg):
    l, w, h, kg = case
    L, W = pallet
    per_layer = max((L // l) * (W // w), (L // w) * (W // l))
    if per_layer == 0:
        return [0, 0, 0, 15, 25]
    layers = (max_h - 15 - h) // h
    by_weight = (max_kg - 25) // kg
    cases = min(per_layer * layers, by_weight)
    if cases <= 0:
        return [per_layer, 0, 0, 15, 25]
    full = -(-cases // per_layer)
    return [per_layer, full, cases, 15 + full * h, 25 + cases * kg]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['generated mix 2', [[30, 30, 30, 8], [120, 100], 100, 1200], [12, 2, 24, 75, 217]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['generated mix 7', [[40, 30, 20, 5], [120, 80], 140, 1025], [8, 6, 48, 135, 265]], ['generated mix 15', [[50, 20, 30, 8], [120, 80], 115, 800], [8, 3, 24, 105, 217]]], [['generated mix 23', [[25, 25, 25, 12], [120, 100], 100, 800], [16, 3, 48, 90, 601]], ['generated mix 7', [[40, 30, 20, 5], [120, 80], 140, 1025], [8, 6, 48, 135, 265]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['generated mix 10', [[30, 15, 20, 5], [120, 80], 190, 1025], [20, 8, 160, 175, 825]], ['generated mix 18', [[30, 25, 10, 2], [120, 100], 115, 1025], [16, 10, 160, 115, 345]]], [['generated mix 55', [[50, 30, 30, 5], [120, 100], 190, 1200], [8, 5, 40, 165, 225]], ['generated mix 12', [[40, 15, 30, 12], [120, 80], 140, 1200], [16, 4, 64, 135, 793]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['generated mix 21', [[25, 20, 30, 2], [120, 80], 140, 300], [18, 4, 72, 135, 169]], ['generated mix 29', [[50, 30, 30, 20], [120, 100], 190, 300], [8, 2, 13, 75, 285]]], [['generated mix 2', [[30, 30, 30, 8], [120, 100], 100, 1200], [12, 2, 24, 75, 217]], ['generated mix 17', [[30, 30, 30, 8], [120, 80], 165, 500], [8, 5, 40, 165, 345]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['generated mix 33', [[40, 30, 10, 20], [120, 80], 165, 800], [8, 5, 38, 65, 785]], ['generated mix 41', [[25, 25, 10, 20], [120, 100], 165, 1200], [16, 4, 58, 55, 1185]]], [['generated mix 23', [[25, 25, 25, 12], [120, 100], 100, 800], [16, 3, 48, 90, 601]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['generated mix 43', [[25, 20, 20, 12], [120, 100], 140, 1200], [24, 5, 97, 115, 1189]], ['generated mix 51', [[25, 15, 10, 8], [120, 80], 165, 500], [24, 3, 59, 45, 497]], ['generated mix 59', [[30, 15, 10, 20], [120, 80], 165, 500], [20, 2, 23, 35, 485]]]]
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
generated mix 2[12, 1, 12, 45, 121][12, 2, 24, 75, 217]Failed
rotation wins[8, 4, 32, 95, 185][8, 5, 40, 115, 225]Failed
listed orientation wins[20, 4, 80, 95, 425][20, 5, 100, 115, 525]Failed
weight bound partial layer[9, 3, 20, 90, 425][9, 3, 20, 90, 425]Passed
too heavy for one[9, 0, 0, 15, 25][9, 0, 0, 15, 25]Passed
height exact[9, 4, 36, 115, 97][9, 5, 45, 140, 115]Failed
generated mix 7[8, 5, 40, 115, 225][8, 6, 48, 135, 265]Failed
generated mix 15[8, 2, 16, 75, 153][8, 3, 24, 105, 217]Failed

SHA-256 / 140037c3fee5e6618ce82f25d9ed206b7213c51e50574d026efa08b03a2b6d4b

3 / The verified repair

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

N = 1
observations = []
def solve(case, pallet, max_h, max_kg):
    l, w, h, kg = case
    L, W = pallet
    per_layer = max((L // l) * (W // w), (L // w) * (W // l))
    if per_layer == 0:
        return [0, 0, 0, 15, 25]
    layers = (max_h - 15) // h
    by_weight = (max_kg - 25) // kg
    cases = min(per_layer * layers, by_weight)
    if cases <= 0:
        return [per_layer, 0, 0, 15, 25]
    full = -(-cases // per_layer)
    return [per_layer, full, cases, 15 + full * h, 25 + cases * kg]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['generated mix 2', [[30, 30, 30, 8], [120, 100], 100, 1200], [12, 2, 24, 75, 217]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['generated mix 7', [[40, 30, 20, 5], [120, 80], 140, 1025], [8, 6, 48, 135, 265]], ['generated mix 15', [[50, 20, 30, 8], [120, 80], 115, 800], [8, 3, 24, 105, 217]]], [['generated mix 23', [[25, 25, 25, 12], [120, 100], 100, 800], [16, 3, 48, 90, 601]], ['generated mix 7', [[40, 30, 20, 5], [120, 80], 140, 1025], [8, 6, 48, 135, 265]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['generated mix 10', [[30, 15, 20, 5], [120, 80], 190, 1025], [20, 8, 160, 175, 825]], ['generated mix 18', [[30, 25, 10, 2], [120, 100], 115, 1025], [16, 10, 160, 115, 345]]], [['generated mix 55', [[50, 30, 30, 5], [120, 100], 190, 1200], [8, 5, 40, 165, 225]], ['generated mix 12', [[40, 15, 30, 12], [120, 80], 140, 1200], [16, 4, 64, 135, 793]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['weight bound partial layer', [[40, 30, 25, 20], [120, 100], 190, 425], [9, 3, 20, 90, 425]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['generated mix 21', [[25, 20, 30, 2], [120, 80], 140, 300], [18, 4, 72, 135, 169]], ['generated mix 29', [[50, 30, 30, 20], [120, 100], 190, 300], [8, 2, 13, 75, 285]]], [['generated mix 2', [[30, 30, 30, 8], [120, 100], 100, 1200], [12, 2, 24, 75, 217]], ['generated mix 17', [[30, 30, 30, 8], [120, 80], 165, 500], [8, 5, 40, 165, 345]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['square', [[25, 25, 30, 5], [120, 80], 165, 900], [12, 5, 60, 165, 325]], ['rotation wins', [[50, 30, 20, 5], [120, 100], 115, 1000], [8, 5, 40, 115, 225]], ['generated mix 33', [[40, 30, 10, 20], [120, 80], 165, 800], [8, 5, 38, 65, 785]], ['generated mix 41', [[25, 25, 10, 20], [120, 100], 165, 1200], [16, 4, 58, 55, 1185]]], [['generated mix 23', [[25, 25, 25, 12], [120, 100], 100, 800], [16, 3, 48, 90, 601]], ['too heavy for one', [[40, 30, 25, 500], [120, 100], 190, 425], [9, 0, 0, 15, 25]], ['listed orientation wins', [[30, 20, 20, 5], [120, 100], 115, 1000], [20, 5, 100, 115, 525]], ['height exact', [[40, 30, 25, 2], [120, 100], 140, 2000], [9, 5, 45, 140, 115]], ['too big', [[130, 30, 25, 2], [120, 100], 190, 425], [0, 0, 0, 15, 25]], ['generated mix 43', [[25, 20, 20, 12], [120, 100], 140, 1200], [24, 5, 97, 115, 1189]], ['generated mix 51', [[25, 15, 10, 8], [120, 80], 165, 500], [24, 3, 59, 45, 497]], ['generated mix 59', [[30, 15, 10, 20], [120, 80], 165, 500], [20, 2, 23, 35, 485]]]]
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
generated mix 2[12, 2, 24, 75, 217][12, 2, 24, 75, 217]Passed
rotation wins[8, 5, 40, 115, 225][8, 5, 40, 115, 225]Passed
listed orientation wins[20, 5, 100, 115, 525][20, 5, 100, 115, 525]Passed
weight bound partial layer[9, 3, 20, 90, 425][9, 3, 20, 90, 425]Passed
too heavy for one[9, 0, 0, 15, 25][9, 0, 0, 15, 25]Passed
height exact[9, 5, 45, 140, 115][9, 5, 45, 140, 115]Passed
generated mix 7[8, 6, 48, 135, 265][8, 6, 48, 135, 265]Passed
generated mix 15[8, 3, 24, 105, 217][8, 3, 24, 105, 217]Passed

SHA-256 / f6f1c30ca481103d39daa169d0a9cd3ca14dad0342f2a9ceb8caadb0bacf7f71

Verification & scope

Uniform-case, single-orientation layer model; no interlocking patterns. 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.615950+00:00.

Case digest / 234bc95a3858b0debf2d9b6d34bb81739f4138b3961868b27f56c505603e4f20