FA-80951 / Music interval and transposition theory / Open access
Enharmonic respelling on a requested letter: respelled note keeps the sounding octave number · case 01
C4 respelled on B is printed B#4 and B3 on C is printed Cb3, an octave off in both cases.
ROOT CAUSE
The octave in the output is derived from the sounding pitch instead of from the chosen letter octave.
VERIFIED REPAIR
Restore the spelled octave output step so that it reads `return letter + sign + str(o)`.
Unsuccessful approach: Using the letter octave only for sharp spellings still prints Cb3 for a Cb that belongs to octave 4.
Case contract
Input [note, letter]. note: letter, accidentals (# +1, b -1, x +2), nonnegative octave. Return the same sounding pitch spelled on the requested letter in whichever octave needs the fewest accidentals, rendering +2 x, +1 #, -1 b, -2 bb; octave numbers follow the letter (B#3 = C4). If more than two accidentals would be needed return 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):
base = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
if not isinstance(x, list) or len(x) != 2:
return None
note, letter = x
if letter not in base or not isinstance(note, str) or len(note) < 2 or note[0] not in base:
return None
i = 1
acc = 0
while i < len(note) and note[i] in '#bx':
acc += {'#': 1, 'b': -1, 'x': 2}[note[i]]
i += 1
if not note[i:].isdigit():
return None
m = 12 * (int(note[i:]) + 1) + base[note[0]] + acc
best = None
for o in range(m // 12 - 2, m // 12 + 1):
shift = m - (12 * (o + 1) + base[letter])
if abs(shift) <= 2 and (best is None or abs(shift) < abs(best[1])):
best = (o, shift)
if best is None:
return None
o, shift = best
sign = {2: 'x', 1: '#', 0: '', -1: 'b', -2: 'bb'}[shift]
return letter + sign + str(m // 12 - 1)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[(['C4', 'B'], 'B#3'), (['B3', 'C'], 'Cb4'), (['E4', 'F'], 'Fb4'), (['F4', 'E'], 'E#4'), (['G4', 'A'], 'Abb4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C0', 'B'], 'B#-1')], [(['B3', 'C'], 'Cb4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C4', 'E'], None), (['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['B#3', 'C'], 'C4'), (['B0', 'C'], 'Cb1')], [(['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['B#3', 'C'], 'C4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['G4', 'F'], 'Fx4'), (['C0', 'B'], 'B#-1'), (['B4', 'C'], 'Cb5')], [(['B3', 'C'], 'Cb4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['G4', 'F'], 'Fx4'), (['D4', 'C'], 'Cx4'), (['B0', 'C'], 'Cb1'), (['E4', 'D'], 'Dx4'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['D4', 'C'], 'Cx4'), (['B0', 'C'], 'Cb1'), (['E4', 'D'], 'Dx4'), (['F4', 'G'], 'Gbb4'), (['C4', 'C'], 'C4'), (['Bb3', 'A'], 'A#3'), (['B4', 'C'], 'Cb5')]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| oracle 0 | B#4 | B#3 | Failed |
| oracle 1 | Cb3 | Cb4 | Failed |
| oracle 2 | Fb4 | Fb4 | Passed |
| oracle 3 | E#4 | E#4 | Passed |
| oracle 4 | Abb4 | Abb4 | Passed |
| oracle 5 | Gx4 | Gx4 | Passed |
| oracle 6 | Dbb4 | Dbb4 | Passed |
| oracle 7 | B#0 | B#-1 | Failed |
SHA-256 / 35b57dfbc56293107557e729b18a5dc7b6aeb9f6cdaf5b0325e735db734426b3
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
base = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
if not isinstance(x, list) or len(x) != 2:
return None
note, letter = x
if letter not in base or not isinstance(note, str) or len(note) < 2 or note[0] not in base:
return None
i = 1
acc = 0
while i < len(note) and note[i] in '#bx':
acc += {'#': 1, 'b': -1, 'x': 2}[note[i]]
i += 1
if not note[i:].isdigit():
return None
m = 12 * (int(note[i:]) + 1) + base[note[0]] + acc
best = None
for o in range(m // 12 - 2, m // 12 + 1):
shift = m - (12 * (o + 1) + base[letter])
if abs(shift) <= 2 and (best is None or abs(shift) < abs(best[1])):
best = (o, shift)
if best is None:
return None
o, shift = best
sign = {2: 'x', 1: '#', 0: '', -1: 'b', -2: 'bb'}[shift]
return letter + sign + str(o if shift >= 0 else m // 12 - 1)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[(['C4', 'B'], 'B#3'), (['B3', 'C'], 'Cb4'), (['E4', 'F'], 'Fb4'), (['F4', 'E'], 'E#4'), (['G4', 'A'], 'Abb4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C0', 'B'], 'B#-1')], [(['B3', 'C'], 'Cb4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C4', 'E'], None), (['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['B#3', 'C'], 'C4'), (['B0', 'C'], 'Cb1')], [(['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['B#3', 'C'], 'C4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['G4', 'F'], 'Fx4'), (['C0', 'B'], 'B#-1'), (['B4', 'C'], 'Cb5')], [(['B3', 'C'], 'Cb4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['G4', 'F'], 'Fx4'), (['D4', 'C'], 'Cx4'), (['B0', 'C'], 'Cb1'), (['E4', 'D'], 'Dx4'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['D4', 'C'], 'Cx4'), (['B0', 'C'], 'Cb1'), (['E4', 'D'], 'Dx4'), (['F4', 'G'], 'Gbb4'), (['C4', 'C'], 'C4'), (['Bb3', 'A'], 'A#3'), (['B4', 'C'], 'Cb5')]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| oracle 0 | B#3 | B#3 | Passed |
| oracle 1 | Cb3 | Cb4 | Failed |
| oracle 2 | Fb4 | Fb4 | Passed |
| oracle 3 | E#4 | E#4 | Passed |
| oracle 4 | Abb4 | Abb4 | Passed |
| oracle 5 | Gx4 | Gx4 | Passed |
| oracle 6 | Dbb4 | Dbb4 | Passed |
| oracle 7 | B#-1 | B#-1 | Passed |
SHA-256 / 716da2facb170d3687329c7e209fdadfe573d0d931cb0eee04b0db8793c3f709
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
base = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
if not isinstance(x, list) or len(x) != 2:
return None
note, letter = x
if letter not in base or not isinstance(note, str) or len(note) < 2 or note[0] not in base:
return None
i = 1
acc = 0
while i < len(note) and note[i] in '#bx':
acc += {'#': 1, 'b': -1, 'x': 2}[note[i]]
i += 1
if not note[i:].isdigit():
return None
m = 12 * (int(note[i:]) + 1) + base[note[0]] + acc
best = None
for o in range(m // 12 - 2, m // 12 + 1):
shift = m - (12 * (o + 1) + base[letter])
if abs(shift) <= 2 and (best is None or abs(shift) < abs(best[1])):
best = (o, shift)
if best is None:
return None
o, shift = best
sign = {2: 'x', 1: '#', 0: '', -1: 'b', -2: 'bb'}[shift]
return letter + sign + str(o)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[(['C4', 'B'], 'B#3'), (['B3', 'C'], 'Cb4'), (['E4', 'F'], 'Fb4'), (['F4', 'E'], 'E#4'), (['G4', 'A'], 'Abb4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C0', 'B'], 'B#-1')], [(['B3', 'C'], 'Cb4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C4', 'E'], None), (['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['B#3', 'C'], 'C4'), (['B0', 'C'], 'Cb1')], [(['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['B#3', 'C'], 'C4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['G4', 'F'], 'Fx4'), (['C0', 'B'], 'B#-1'), (['B4', 'C'], 'Cb5')], [(['B3', 'C'], 'Cb4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['G4', 'F'], 'Fx4'), (['D4', 'C'], 'Cx4'), (['B0', 'C'], 'Cb1'), (['E4', 'D'], 'Dx4'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['D4', 'C'], 'Cx4'), (['B0', 'C'], 'Cb1'), (['E4', 'D'], 'Dx4'), (['F4', 'G'], 'Gbb4'), (['C4', 'C'], 'C4'), (['Bb3', 'A'], 'A#3'), (['B4', 'C'], 'Cb5')]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| oracle 0 | B#3 | B#3 | Passed |
| oracle 1 | Cb4 | Cb4 | Passed |
| oracle 2 | Fb4 | Fb4 | Passed |
| oracle 3 | E#4 | E#4 | Passed |
| oracle 4 | Abb4 | Abb4 | Passed |
| oracle 5 | Gx4 | Gx4 | Passed |
| oracle 6 | Dbb4 | Dbb4 | Passed |
| oracle 7 | B#-1 | B#-1 | Passed |
SHA-256 / 9012f4dc4939e13a75f51d914ceb39e05738e9bd9ce525c48bb7679ae30ac78b
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:49:58.613165+00:00.
Case digest / b5e6d169ed4284968004a18abd82529fa823875bd378e49646b0128d3b3a9919