FAILURE MAP
← Case archive

FA-81221 / Music interval and transposition theory / Open access

Melody transposition fitted into an instrument range: melody filling the exact range rejected · case 01

A melody spanning exactly the instrument range (C4 to C5 into 60..72) is rejected.

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

ROOT CAUSE

The span precheck treats a span equal to the range width as too wide.

VERIFIED REPAIR

Restore the span precheck step so that it reads `high - low > hi - lo`.

Unsuccessful approach: Counting the span inclusively is the same off-by-one: an exact fit is still rejected.

Case contract

Input [notes, semitones, lo, hi]. Transpose every note by the semitone amount, then shift the whole melody by the octave offset k (|k| <= 10) of smallest magnitude that places every note within [lo, hi] inclusive. Return the notes, or None if the melody is empty, lo > hi, or no octave fits.

Why this case matters

Arranging tools transpose parts into playable instrument ranges.

1 / The failure

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

N = 1
observations = []
def solve(x):
    if not isinstance(x, list) or len(x) != 4:
        return None
    notes, t, lo, hi = x
    if not notes or lo > hi:
        return None
    moved = [n + t for n in notes]
    low, high = min(moved), max(moved)
    if high - low >= hi - lo:
        return None
    options = []
    for k in range(-10, 11):
        if lo <= low + 12 * k and high + 12 * k <= hi:
            options.append((abs(k), k))
    if not options:
        return None
    k = min(options)[1]
    return [n + 12 * k for n in moved]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([[60, 64, 67], 0, 55, 79], [60, 64, 67]), ([[60, 64, 67], 2, 55, 79], [62, 66, 69]), ([[60, 64, 67], 0, 72, 96], [72, 76, 79]), ([[60, 64, 67], 0, 36, 60], [48, 52, 55]), ([[60, 72], 0, 60, 72], [60, 72]), ([[60, 72], 0, 61, 73], None), ([[60, 64], 0, 54, 78], [60, 64]), ([[59, 61], 0, 47, 49], [47, 49])], [([[60, 64, 67], 0, 36, 60], [48, 52, 55]), ([[60, 72], 0, 60, 72], [60, 72]), ([[60, 72], 0, 61, 73], None), ([[60, 64], 0, 54, 78], [60, 64]), ([[60, 62], 5, 40, 50], [41, 43]), ([[60, 79], 0, 60, 78], None), ([[70], 0, 52, 64], [58]), ([[60], 0, 48, 48], [48])], [([[60, 62], 5, 40, 50], [41, 43]), ([[60, 79], 0, 60, 78], None), ([[70], 0, 52, 64], [58]), ([[70], 0, 58, 70], [70]), ([[48, 50], -2, 50, 70], [58, 60]), ([[], 0, 0, 127], None), ([[60], 0, 48, 48], [48]), ([[59, 61], 0, 47, 49], [47, 49])], [([[60, 72], 0, 60, 72], [60, 72]), ([[70], 0, 58, 70], [70]), ([[48, 50], -2, 50, 70], [58, 60]), ([[], 0, 0, 127], None), ([[60], 0, 70, 60], None), ([[60, 64, 67], -12, 55, 79], [60, 64, 67]), ([[60], 6, 54, 67], [66]), ([[59, 61], 0, 47, 49], [47, 49])], [([[60, 72], 0, 60, 72], [60, 72]), ([[60], 0, 70, 60], None), ([[60, 64, 67], -12, 55, 79], [60, 64, 67]), ([[60], 6, 54, 67], [66]), ([[62, 65], 0, 50, 62], [50, 53]), ([[60, 67], 0, 62, 73], None), ([[60, 63], 3, 48, 60], [51, 54]), ([[60], 0, 48, 48], [48])]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("oracle %d" % i, 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
oracle 0[60, 64, 67][60, 64, 67]Passed
oracle 1[62, 66, 69][62, 66, 69]Passed
oracle 2[72, 76, 79][72, 76, 79]Passed
oracle 3[48, 52, 55][48, 52, 55]Passed
oracle 4None[60, 72]Failed
oracle 5NoneNonePassed
oracle 6[60, 64][60, 64]Passed
oracle 7None[47, 49]Failed

SHA-256 / 9fefda1b943cb459f1f0c1738de4def6ad05521ff48797434b495541d2f5bc72

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    if not isinstance(x, list) or len(x) != 4:
        return None
    notes, t, lo, hi = x
    if not notes or lo > hi:
        return None
    moved = [n + t for n in notes]
    low, high = min(moved), max(moved)
    if high - low + 1 > hi - lo:
        return None
    options = []
    for k in range(-10, 11):
        if lo <= low + 12 * k and high + 12 * k <= hi:
            options.append((abs(k), k))
    if not options:
        return None
    k = min(options)[1]
    return [n + 12 * k for n in moved]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([[60, 64, 67], 0, 55, 79], [60, 64, 67]), ([[60, 64, 67], 2, 55, 79], [62, 66, 69]), ([[60, 64, 67], 0, 72, 96], [72, 76, 79]), ([[60, 64, 67], 0, 36, 60], [48, 52, 55]), ([[60, 72], 0, 60, 72], [60, 72]), ([[60, 72], 0, 61, 73], None), ([[60, 64], 0, 54, 78], [60, 64]), ([[59, 61], 0, 47, 49], [47, 49])], [([[60, 64, 67], 0, 36, 60], [48, 52, 55]), ([[60, 72], 0, 60, 72], [60, 72]), ([[60, 72], 0, 61, 73], None), ([[60, 64], 0, 54, 78], [60, 64]), ([[60, 62], 5, 40, 50], [41, 43]), ([[60, 79], 0, 60, 78], None), ([[70], 0, 52, 64], [58]), ([[60], 0, 48, 48], [48])], [([[60, 62], 5, 40, 50], [41, 43]), ([[60, 79], 0, 60, 78], None), ([[70], 0, 52, 64], [58]), ([[70], 0, 58, 70], [70]), ([[48, 50], -2, 50, 70], [58, 60]), ([[], 0, 0, 127], None), ([[60], 0, 48, 48], [48]), ([[59, 61], 0, 47, 49], [47, 49])], [([[60, 72], 0, 60, 72], [60, 72]), ([[70], 0, 58, 70], [70]), ([[48, 50], -2, 50, 70], [58, 60]), ([[], 0, 0, 127], None), ([[60], 0, 70, 60], None), ([[60, 64, 67], -12, 55, 79], [60, 64, 67]), ([[60], 6, 54, 67], [66]), ([[59, 61], 0, 47, 49], [47, 49])], [([[60, 72], 0, 60, 72], [60, 72]), ([[60], 0, 70, 60], None), ([[60, 64, 67], -12, 55, 79], [60, 64, 67]), ([[60], 6, 54, 67], [66]), ([[62, 65], 0, 50, 62], [50, 53]), ([[60, 67], 0, 62, 73], None), ([[60, 63], 3, 48, 60], [51, 54]), ([[60], 0, 48, 48], [48])]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("oracle %d" % i, 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
oracle 0[60, 64, 67][60, 64, 67]Passed
oracle 1[62, 66, 69][62, 66, 69]Passed
oracle 2[72, 76, 79][72, 76, 79]Passed
oracle 3[48, 52, 55][48, 52, 55]Passed
oracle 4None[60, 72]Failed
oracle 5NoneNonePassed
oracle 6[60, 64][60, 64]Passed
oracle 7None[47, 49]Failed

SHA-256 / 168f553a8e694db7c5501d40470f150242bf1fcc8d7155c737b031be73753e2c

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    if not isinstance(x, list) or len(x) != 4:
        return None
    notes, t, lo, hi = x
    if not notes or lo > hi:
        return None
    moved = [n + t for n in notes]
    low, high = min(moved), max(moved)
    if high - low > hi - lo:
        return None
    options = []
    for k in range(-10, 11):
        if lo <= low + 12 * k and high + 12 * k <= hi:
            options.append((abs(k), k))
    if not options:
        return None
    k = min(options)[1]
    return [n + 12 * k for n in moved]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([[60, 64, 67], 0, 55, 79], [60, 64, 67]), ([[60, 64, 67], 2, 55, 79], [62, 66, 69]), ([[60, 64, 67], 0, 72, 96], [72, 76, 79]), ([[60, 64, 67], 0, 36, 60], [48, 52, 55]), ([[60, 72], 0, 60, 72], [60, 72]), ([[60, 72], 0, 61, 73], None), ([[60, 64], 0, 54, 78], [60, 64]), ([[59, 61], 0, 47, 49], [47, 49])], [([[60, 64, 67], 0, 36, 60], [48, 52, 55]), ([[60, 72], 0, 60, 72], [60, 72]), ([[60, 72], 0, 61, 73], None), ([[60, 64], 0, 54, 78], [60, 64]), ([[60, 62], 5, 40, 50], [41, 43]), ([[60, 79], 0, 60, 78], None), ([[70], 0, 52, 64], [58]), ([[60], 0, 48, 48], [48])], [([[60, 62], 5, 40, 50], [41, 43]), ([[60, 79], 0, 60, 78], None), ([[70], 0, 52, 64], [58]), ([[70], 0, 58, 70], [70]), ([[48, 50], -2, 50, 70], [58, 60]), ([[], 0, 0, 127], None), ([[60], 0, 48, 48], [48]), ([[59, 61], 0, 47, 49], [47, 49])], [([[60, 72], 0, 60, 72], [60, 72]), ([[70], 0, 58, 70], [70]), ([[48, 50], -2, 50, 70], [58, 60]), ([[], 0, 0, 127], None), ([[60], 0, 70, 60], None), ([[60, 64, 67], -12, 55, 79], [60, 64, 67]), ([[60], 6, 54, 67], [66]), ([[59, 61], 0, 47, 49], [47, 49])], [([[60, 72], 0, 60, 72], [60, 72]), ([[60], 0, 70, 60], None), ([[60, 64, 67], -12, 55, 79], [60, 64, 67]), ([[60], 6, 54, 67], [66]), ([[62, 65], 0, 50, 62], [50, 53]), ([[60, 67], 0, 62, 73], None), ([[60, 63], 3, 48, 60], [51, 54]), ([[60], 0, 48, 48], [48])]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("oracle %d" % i, 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
oracle 0[60, 64, 67][60, 64, 67]Passed
oracle 1[62, 66, 69][62, 66, 69]Passed
oracle 2[72, 76, 79][72, 76, 79]Passed
oracle 3[48, 52, 55][48, 52, 55]Passed
oracle 4[60, 72][60, 72]Passed
oracle 5NoneNonePassed
oracle 6[60, 64][60, 64]Passed
oracle 7[47, 49][47, 49]Passed

SHA-256 / 48ad36f99722bd63da5bfe20a69f0858bed8945193b1fbcd2dbc299663e87ce3

Verification & scope

A deterministic bounded teaching model with a stipulated toy contract; it is not a complete music notation or theory engine. 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:50:01.145120+00:00.

Case digest / e6b111f669ebdeb23ca109f6f24952a9ffb27cb85920be04acedde0ab3f6369a