FA-80941 / Music interval and transposition theory / Open access
Enharmonic respelling on a requested letter: B sharp octave never searched · case 01
Respelling C4 on B returns None because the octave holding B#3 is outside the search window.
ROOT CAUSE
The octave scan starts one octave too high, skipping the letter octave below the sounding octave.
VERIFIED REPAIR
Restore the octave candidate window step so that it reads `range(m // 12 - 2, m // 12 + 1)`.
Unsuccessful approach: Shifting the window down now misses the octave above, so B3 cannot be respelled as Cb4.
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 - 1, 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'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C4', 'E'], None), (['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['C0', 'B'], 'B#-1'), (['B0', 'C'], 'Cb1')], [(['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['B#3', 'C'], 'C4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['C0', 'B'], 'B#-1'), (['B4', 'C'], 'Cb5'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['B3', 'C'], 'Cb4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['G4', 'F'], 'Fx4'), (['D4', 'C'], 'Cx4'), (['E4', 'D'], 'Dx4'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['D4', 'C'], 'Cx4'), (['C0', 'B'], 'B#-1'), (['B0', 'C'], 'Cb1'), (['E4', 'D'], 'Dx4'), (['F4', 'G'], 'Gbb4'), (['C4', 'C'], 'C4'), (['Bb3', 'A'], 'A#3')]]
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 | None | B#3 | Failed |
| 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 | None | B#4 | Failed |
SHA-256 / a4b593f1972e4887cd3d89a9e430d3c31e19f13838e9bba64a08c5597f93d6ff
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):
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'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C4', 'E'], None), (['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['C0', 'B'], 'B#-1'), (['B0', 'C'], 'Cb1')], [(['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['B#3', 'C'], 'C4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['C0', 'B'], 'B#-1'), (['B4', 'C'], 'Cb5'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['B3', 'C'], 'Cb4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['G4', 'F'], 'Fx4'), (['D4', 'C'], 'Cx4'), (['E4', 'D'], 'Dx4'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['D4', 'C'], 'Cx4'), (['C0', 'B'], 'B#-1'), (['B0', 'C'], 'Cb1'), (['E4', 'D'], 'Dx4'), (['F4', 'G'], 'Gbb4'), (['C4', 'C'], 'C4'), (['Bb3', 'A'], 'A#3')]]
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 | None | 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#4 | B#4 | Passed |
SHA-256 / 60cb4119fc018e602d5fbe1d0a5ef33466bc6e8e9419ebc6644e4512f763ce36
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'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C4', 'E'], None), (['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['C0', 'B'], 'B#-1'), (['B0', 'C'], 'Cb1')], [(['C#4', 'D'], 'Db4'), (['Db4', 'C'], 'C#4'), (['B#3', 'C'], 'C4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['C0', 'B'], 'B#-1'), (['B4', 'C'], 'Cb5'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['B3', 'C'], 'Cb4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4'), (['G4', 'F'], 'Fx4'), (['D4', 'C'], 'Cx4'), (['E4', 'D'], 'Dx4'), (['C5', 'B'], 'B#4')], [(['C4', 'B'], 'B#3'), (['D4', 'C'], 'Cx4'), (['C0', 'B'], 'B#-1'), (['B0', 'C'], 'Cb1'), (['E4', 'D'], 'Dx4'), (['F4', 'G'], 'Gbb4'), (['C4', 'C'], 'C4'), (['Bb3', 'A'], 'A#3')]]
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#4 | B#4 | Passed |
SHA-256 / 56905601af67e58c7b0084bc1df0c1a337d795e0d140e422ef70ca59f041f0a1
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.585965+00:00.
Case digest / 0d978f45d1f110f26c21cef8c443a09afee4b5686453a32f12daf524a2f72541