FA-80861 / Music interval and transposition theory / Open access
Spelled pitch to MIDI key number: double sharp glyph not consumed · case 01
Any spelling with an x double sharp (Fx4, Cx-1) is rejected as malformed.
ROOT CAUSE
The accidental scanner only consumes # and b, so the x glyph is left in the octave field.
VERIFIED REPAIR
Restore the accidental run step so that it reads `x[i] in '#bx'`.
Unsuccessful approach: Admitting x but capping the scan at two accidentals rejects legal triple accidentals such as Dbbb4 and Cxx4.
Case contract
Input a spelled pitch string: uppercase letter A-G, any run of accidentals (# = +1, b = -1, x = +2), then a signed integer octave where C4 = 60 and C-1 = 0. Return the MIDI key number, or None for malformed text or results outside 0..127.
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):
names = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
if not isinstance(x, str) or len(x) < 2 or x[0] not in names:
return None
i = 1
acc = 0
while i < len(x) and x[i] in '#b':
acc += {'#': 1, 'b': -1, 'x': 2}[x[i]]
i += 1
tail = x[i:]
neg = tail.startswith('-')
digits = tail[1:] if neg else tail
if not digits.isdigit():
return None
octave = -int(digits) if neg else int(digits)
midi = (octave + 1) * 12 + names[x[0]] + acc
if midi < 0 or midi > 127:
return None
return midi
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('C4', 60), ('A4', 69), ('C-1', 0), ('G9', 127), ('G#9', None), ('Fx4', 67), ('Dbbb4', 59), ('Cxx4', 64)], [('G9', 127), ('G#9', None), ('Ab9', None), ('B#3', 60), ('Cb4', 59), ('Dbbb4', 59), ('Cx-1', 2), ('Bx-1', 13)], [('B#3', 60), ('Cb4', 59), ('Fx4', 67), ('Ebb4', 62), ('Dbbb4', 59), ('Cb-1', None), ('B-1', 11), ('Cxx4', 64)], [('Dbbb4', 59), ('Cb-1', None), ('B-1', 11), ('E4', 64), ('F4', 65), ('B4', 71), ('Cx-1', 2), ('Bx-1', 13)], [('Fx4', 67), ('Dbbb4', 59), ('F4', 65), ('B4', 71), ('Bb3', 58), ('C0', 12), ('D#0', 15), ('Cxx4', 64)]]
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 | 60 | 60 | Passed |
| oracle 1 | 69 | 69 | Passed |
| oracle 2 | 0 | 0 | Passed |
| oracle 3 | 127 | 127 | Passed |
| oracle 4 | None | None | Passed |
| oracle 5 | None | 67 | Failed |
| oracle 6 | 59 | 59 | Passed |
| oracle 7 | None | 64 | Failed |
SHA-256 / 91b8280f9c895b67512ff42d563ed243a41190f508bf7e789e4178a6631e9f19
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
names = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
if not isinstance(x, str) or len(x) < 2 or x[0] not in names:
return None
i = 1
acc = 0
while i < len(x) and x[i] in '#bx' and i < 3:
acc += {'#': 1, 'b': -1, 'x': 2}[x[i]]
i += 1
tail = x[i:]
neg = tail.startswith('-')
digits = tail[1:] if neg else tail
if not digits.isdigit():
return None
octave = -int(digits) if neg else int(digits)
midi = (octave + 1) * 12 + names[x[0]] + acc
if midi < 0 or midi > 127:
return None
return midi
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('C4', 60), ('A4', 69), ('C-1', 0), ('G9', 127), ('G#9', None), ('Fx4', 67), ('Dbbb4', 59), ('Cxx4', 64)], [('G9', 127), ('G#9', None), ('Ab9', None), ('B#3', 60), ('Cb4', 59), ('Dbbb4', 59), ('Cx-1', 2), ('Bx-1', 13)], [('B#3', 60), ('Cb4', 59), ('Fx4', 67), ('Ebb4', 62), ('Dbbb4', 59), ('Cb-1', None), ('B-1', 11), ('Cxx4', 64)], [('Dbbb4', 59), ('Cb-1', None), ('B-1', 11), ('E4', 64), ('F4', 65), ('B4', 71), ('Cx-1', 2), ('Bx-1', 13)], [('Fx4', 67), ('Dbbb4', 59), ('F4', 65), ('B4', 71), ('Bb3', 58), ('C0', 12), ('D#0', 15), ('Cxx4', 64)]]
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 | 60 | 60 | Passed |
| oracle 1 | 69 | 69 | Passed |
| oracle 2 | 0 | 0 | Passed |
| oracle 3 | 127 | 127 | Passed |
| oracle 4 | None | None | Passed |
| oracle 5 | 67 | 67 | Passed |
| oracle 6 | None | 59 | Failed |
| oracle 7 | 64 | 64 | Passed |
SHA-256 / 06cbb27ba75473c1b2bc286a7f25215eaac8678a03eb46591fc9432178f7ed82
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
names = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
if not isinstance(x, str) or len(x) < 2 or x[0] not in names:
return None
i = 1
acc = 0
while i < len(x) and x[i] in '#bx':
acc += {'#': 1, 'b': -1, 'x': 2}[x[i]]
i += 1
tail = x[i:]
neg = tail.startswith('-')
digits = tail[1:] if neg else tail
if not digits.isdigit():
return None
octave = -int(digits) if neg else int(digits)
midi = (octave + 1) * 12 + names[x[0]] + acc
if midi < 0 or midi > 127:
return None
return midi
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('C4', 60), ('A4', 69), ('C-1', 0), ('G9', 127), ('G#9', None), ('Fx4', 67), ('Dbbb4', 59), ('Cxx4', 64)], [('G9', 127), ('G#9', None), ('Ab9', None), ('B#3', 60), ('Cb4', 59), ('Dbbb4', 59), ('Cx-1', 2), ('Bx-1', 13)], [('B#3', 60), ('Cb4', 59), ('Fx4', 67), ('Ebb4', 62), ('Dbbb4', 59), ('Cb-1', None), ('B-1', 11), ('Cxx4', 64)], [('Dbbb4', 59), ('Cb-1', None), ('B-1', 11), ('E4', 64), ('F4', 65), ('B4', 71), ('Cx-1', 2), ('Bx-1', 13)], [('Fx4', 67), ('Dbbb4', 59), ('F4', 65), ('B4', 71), ('Bb3', 58), ('C0', 12), ('D#0', 15), ('Cxx4', 64)]]
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 | 60 | 60 | Passed |
| oracle 1 | 69 | 69 | Passed |
| oracle 2 | 0 | 0 | Passed |
| oracle 3 | 127 | 127 | Passed |
| oracle 4 | None | None | Passed |
| oracle 5 | 67 | 67 | Passed |
| oracle 6 | 59 | 59 | Passed |
| oracle 7 | 64 | 64 | Passed |
SHA-256 / a927af4835099cbe02db21696cb8fe4a16b8e0616252500a93a665be30d24084
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:57.730302+00:00.
Case digest / dac6b600aebf9f7696ad9bbd6e3839b4abe0c7b329c0fb489946f6e07fe3b2fa