FA-80956 / Music interval and transposition theory / Open access
Enharmonic respelling on a requested letter: alteration measured from pitch to letter · case 01
C#4 respelled on D prints D#4 instead of Db4: every accidental points the wrong way.
ROOT CAUSE
The alteration subtracts the sounding pitch from the natural letter instead of the reverse.
VERIFIED REPAIR
Restore the alteration sign step so that it reads `shift = m - (12 * (o + 1) + base[letter])`.
Unsuccessful approach: Taking the absolute distance turns every flat into a sharp and can pick the wrong octave.
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 = (12 * (o + 1) + base[letter]) - m
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'), (['C4', 'D'], 'Dbb4'), (['C4', 'E'], None), (['B#3', 'C'], 'C4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4')], [(['B3', 'C'], 'Cb4'), (['E4', 'F'], 'Fb4'), (['F4', 'E'], 'E#4'), (['C#4', 'D'], 'Db4'), (['Fx4', 'G'], 'G4'), (['C4', 'C'], 'C4'), (['C4', 'H'], None), (['C4', None], None)], [(['E4', 'F'], 'Fb4'), (['G4', 'A'], 'Abb4'), (['B0', 'C'], 'Cb1'), (['C4', None], None), (['E#4', 'F'], 'F4'), (['Fb4', 'E'], 'E4'), (['Ebb4', 'D'], 'D4'), (['Dx4', 'E'], 'E4')], [(['C4', 'B'], 'B#3'), (['B3', 'C'], 'Cb4'), (['F4', 'E'], 'E#4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['F4', 'G'], 'Gbb4'), (['Ebb4', 'D'], 'D4'), (['Dx4', 'E'], 'E4')], [(['B3', 'C'], 'Cb4'), (['E4', 'F'], 'Fb4'), (['F4', 'E'], 'E#4'), (['G4', 'A'], 'Abb4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C#4', 'D'], 'Db4'), (['A#3', 'B'], 'Bb3')]]
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 | Bb3 | B#3 | Failed |
| oracle 1 | C#4 | Cb4 | Failed |
| oracle 2 | F#4 | Fb4 | Failed |
| oracle 3 | Dx4 | Dbb4 | Failed |
| oracle 4 | None | None | Passed |
| oracle 5 | C4 | C4 | Passed |
| oracle 6 | B3 | B3 | Passed |
| oracle 7 | G4 | G4 | Passed |
SHA-256 / 7e4ec4c138b315bb54e3413fb079595a3ae72a9790eb44016d145c34f727913e
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 = abs(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'), (['C4', 'D'], 'Dbb4'), (['C4', 'E'], None), (['B#3', 'C'], 'C4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4')], [(['B3', 'C'], 'Cb4'), (['E4', 'F'], 'Fb4'), (['F4', 'E'], 'E#4'), (['C#4', 'D'], 'Db4'), (['Fx4', 'G'], 'G4'), (['C4', 'C'], 'C4'), (['C4', 'H'], None), (['C4', None], None)], [(['E4', 'F'], 'Fb4'), (['G4', 'A'], 'Abb4'), (['B0', 'C'], 'Cb1'), (['C4', None], None), (['E#4', 'F'], 'F4'), (['Fb4', 'E'], 'E4'), (['Ebb4', 'D'], 'D4'), (['Dx4', 'E'], 'E4')], [(['C4', 'B'], 'B#3'), (['B3', 'C'], 'Cb4'), (['F4', 'E'], 'E#4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['F4', 'G'], 'Gbb4'), (['Ebb4', 'D'], 'D4'), (['Dx4', 'E'], 'E4')], [(['B3', 'C'], 'Cb4'), (['E4', 'F'], 'Fb4'), (['F4', 'E'], 'E#4'), (['G4', 'A'], 'Abb4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C#4', 'D'], 'Db4'), (['A#3', 'B'], 'Bb3')]]
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 | C#4 | Cb4 | Failed |
| oracle 2 | F#4 | Fb4 | Failed |
| oracle 3 | Dx4 | Dbb4 | Failed |
| oracle 4 | None | None | Passed |
| oracle 5 | C4 | C4 | Passed |
| oracle 6 | B3 | B3 | Passed |
| oracle 7 | G4 | G4 | Passed |
SHA-256 / 33545518a33d697fabc32e108b983dfb2e5624059e98c6f219aebe3ec6ca3cba
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'), (['C4', 'D'], 'Dbb4'), (['C4', 'E'], None), (['B#3', 'C'], 'C4'), (['Cb4', 'B'], 'B3'), (['Fx4', 'G'], 'G4')], [(['B3', 'C'], 'Cb4'), (['E4', 'F'], 'Fb4'), (['F4', 'E'], 'E#4'), (['C#4', 'D'], 'Db4'), (['Fx4', 'G'], 'G4'), (['C4', 'C'], 'C4'), (['C4', 'H'], None), (['C4', None], None)], [(['E4', 'F'], 'Fb4'), (['G4', 'A'], 'Abb4'), (['B0', 'C'], 'Cb1'), (['C4', None], None), (['E#4', 'F'], 'F4'), (['Fb4', 'E'], 'E4'), (['Ebb4', 'D'], 'D4'), (['Dx4', 'E'], 'E4')], [(['C4', 'B'], 'B#3'), (['B3', 'C'], 'Cb4'), (['F4', 'E'], 'E#4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['F4', 'G'], 'Gbb4'), (['Ebb4', 'D'], 'D4'), (['Dx4', 'E'], 'E4')], [(['B3', 'C'], 'Cb4'), (['E4', 'F'], 'Fb4'), (['F4', 'E'], 'E#4'), (['G4', 'A'], 'Abb4'), (['A4', 'G'], 'Gx4'), (['C4', 'D'], 'Dbb4'), (['C#4', 'D'], 'Db4'), (['A#3', 'B'], 'Bb3')]]
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 | Dbb4 | Dbb4 | Passed |
| oracle 4 | None | None | Passed |
| oracle 5 | C4 | C4 | Passed |
| oracle 6 | B3 | B3 | Passed |
| oracle 7 | G4 | G4 | Passed |
SHA-256 / 7bfcf2b72b9fb24adabb4bda59058914aab3403dec2b88369766dd37ff2b9fb4
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.616326+00:00.
Case digest / 6bc9e54138ddf43c0946fedea43020fc141ac7bd6aa1d4f83cdd2f0188da8407