FAILURE MAP
← Case archive

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

Interval inversion by quality and number: multi-letter qualities not parsed · case 01

Doubly augmented and doubly diminished intervals such as AA4 are rejected.

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

ROOT CAUSE

The quality is taken to be the first character only.

VERIFIED REPAIR

Restore the quality token split step so that it reads `x.rstrip('0123456789')`.

Unsuccessful approach: Taking everything but the last character breaks two-digit numbers such as M10.

Case contract

Input an interval string: quality from P, M, m, A, d, AA, dd followed by a positive integer. Compound numbers above 8 reduce by 7 until <= 8. P is valid only for 1, 4, 5, 8; M and m only for 2, 3, 6, 7. Inversion maps M<->m, A<->d, AA<->dd, P->P and number n -> 9-n. Invalid input returns None.

Why this case matters

Pitch spelling and interval arithmetic decide the notes that notation, transposition and analysis tools display or play.

1 / The failure

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

N = 1
observations = []
def solve(x):
    swap = {'M': 'm', 'm': 'M', 'A': 'd', 'd': 'A', 'AA': 'dd', 'dd': 'AA', 'P': 'P'}
    if not isinstance(x, str):
        return None
    q = x[0]
    digits = x[len(q):]
    if q not in swap or not digits.isdigit() or int(digits) < 1:
        return None
    n = int(digits)
    while n > 8:
        n -= 7
    perfect = n in (1, 4, 5, 8)
    if (q == 'P' and not perfect) or (q in ('M', 'm') and perfect):
        return None
    return swap[q] + str(9 - n)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('M3', 'm6'), ('m3', 'M6'), ('P5', 'P4'), ('P4', 'P5'), ('M10', 'm6'), ('AA4', 'dd5'), ('A11', 'd5'), ('dd7', 'AA2')], [('P4', 'P5'), ('P1', 'P8'), ('P8', 'P1'), ('A4', 'd5'), ('P15', 'P1'), ('dd5', 'AA4'), ('AA6', 'dd3'), ('m14', 'M2')], [('A4', 'd5'), ('d5', 'A4'), ('M2', 'm7'), ('m7', 'M2'), ('P12', 'P4'), ('AA4', 'dd5'), ('dd7', 'AA2'), ('P22', 'P1')], [('m7', 'M2'), ('M10', 'm6'), ('dd5', 'AA4'), ('A1', 'd8'), ('d8', 'A1'), ('M6', 'm3'), ('A11', 'd5'), ('AA6', 'dd3')], [('P15', 'P1'), ('AA4', 'dd5'), ('M6', 'm3'), ('m9', 'M7'), ('P3', None), ('M4', None), ('dd7', 'AA2'), ('m14', 'M2')]]
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 0m6m6Passed
oracle 1M6M6Passed
oracle 2P4P4Passed
oracle 3P5P5Passed
oracle 4m6m6Passed
oracle 5Nonedd5Failed
oracle 6d5d5Passed
oracle 7NoneAA2Failed

SHA-256 / 5682edbb0faba2f580c09a15ef5004cfd82a7175987b7340877da6a7eaeb946d

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    swap = {'M': 'm', 'm': 'M', 'A': 'd', 'd': 'A', 'AA': 'dd', 'dd': 'AA', 'P': 'P'}
    if not isinstance(x, str):
        return None
    q = x[:-1]
    digits = x[len(q):]
    if q not in swap or not digits.isdigit() or int(digits) < 1:
        return None
    n = int(digits)
    while n > 8:
        n -= 7
    perfect = n in (1, 4, 5, 8)
    if (q == 'P' and not perfect) or (q in ('M', 'm') and perfect):
        return None
    return swap[q] + str(9 - n)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('M3', 'm6'), ('m3', 'M6'), ('P5', 'P4'), ('P4', 'P5'), ('M10', 'm6'), ('AA4', 'dd5'), ('A11', 'd5'), ('dd7', 'AA2')], [('P4', 'P5'), ('P1', 'P8'), ('P8', 'P1'), ('A4', 'd5'), ('P15', 'P1'), ('dd5', 'AA4'), ('AA6', 'dd3'), ('m14', 'M2')], [('A4', 'd5'), ('d5', 'A4'), ('M2', 'm7'), ('m7', 'M2'), ('P12', 'P4'), ('AA4', 'dd5'), ('dd7', 'AA2'), ('P22', 'P1')], [('m7', 'M2'), ('M10', 'm6'), ('dd5', 'AA4'), ('A1', 'd8'), ('d8', 'A1'), ('M6', 'm3'), ('A11', 'd5'), ('AA6', 'dd3')], [('P15', 'P1'), ('AA4', 'dd5'), ('M6', 'm3'), ('m9', 'M7'), ('P3', None), ('M4', None), ('dd7', 'AA2'), ('m14', 'M2')]]
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 0m6m6Passed
oracle 1M6M6Passed
oracle 2P4P4Passed
oracle 3P5P5Passed
oracle 4Nonem6Failed
oracle 5dd5dd5Passed
oracle 6Noned5Failed
oracle 7AA2AA2Passed

SHA-256 / 15a9a71b5d2c297eb388dd324eb77c12d513c9b3e29e72a97c6fa5991d5b3cbb

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    swap = {'M': 'm', 'm': 'M', 'A': 'd', 'd': 'A', 'AA': 'dd', 'dd': 'AA', 'P': 'P'}
    if not isinstance(x, str):
        return None
    q = x.rstrip('0123456789')
    digits = x[len(q):]
    if q not in swap or not digits.isdigit() or int(digits) < 1:
        return None
    n = int(digits)
    while n > 8:
        n -= 7
    perfect = n in (1, 4, 5, 8)
    if (q == 'P' and not perfect) or (q in ('M', 'm') and perfect):
        return None
    return swap[q] + str(9 - n)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('M3', 'm6'), ('m3', 'M6'), ('P5', 'P4'), ('P4', 'P5'), ('M10', 'm6'), ('AA4', 'dd5'), ('A11', 'd5'), ('dd7', 'AA2')], [('P4', 'P5'), ('P1', 'P8'), ('P8', 'P1'), ('A4', 'd5'), ('P15', 'P1'), ('dd5', 'AA4'), ('AA6', 'dd3'), ('m14', 'M2')], [('A4', 'd5'), ('d5', 'A4'), ('M2', 'm7'), ('m7', 'M2'), ('P12', 'P4'), ('AA4', 'dd5'), ('dd7', 'AA2'), ('P22', 'P1')], [('m7', 'M2'), ('M10', 'm6'), ('dd5', 'AA4'), ('A1', 'd8'), ('d8', 'A1'), ('M6', 'm3'), ('A11', 'd5'), ('AA6', 'dd3')], [('P15', 'P1'), ('AA4', 'dd5'), ('M6', 'm3'), ('m9', 'M7'), ('P3', None), ('M4', None), ('dd7', 'AA2'), ('m14', 'M2')]]
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 0m6m6Passed
oracle 1M6M6Passed
oracle 2P4P4Passed
oracle 3P5P5Passed
oracle 4m6m6Passed
oracle 5dd5dd5Passed
oracle 6d5d5Passed
oracle 7AA2AA2Passed

SHA-256 / 979bdce485a8936851f0762ca20a445c680c60567839dea2f8433f4506e6ce1a

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

Case digest / c2a83c08e7fa95826c3850797daa0356cacac854d2ead00cdd73e580a09cc333