FA-81306 / Music interval and transposition theory / Open access
Movable-do chromatic solfege syllables: degree measured downward from the tonic · case 01
In C, the note D is sung te or li instead of re because the distance is measured from pitch to tonic.
ROOT CAUSE
The relative pitch class subtracts in the wrong order, mirroring every degree around the tonic.
VERIFIED REPAIR
Restore the relative degree direction step so that it reads `(pitch - tonic) % 12`.
Unsuccessful approach: Taking the absolute difference only works when the pitch lies above the tonic number.
Case contract
Input [tonic_pc, pitch, spelling] with integer pitch values and spelling sharp or flat. The relative pitch class (pitch - tonic) mod 12 maps diatonic degrees to do re mi fa sol la ti; chromatic degrees use di ri fi si li for sharp spelling and ra me se le te for flat spelling. Invalid input returns None.
Why this case matters
Ear-training and sight-singing apps label notes with movable-do syllables relative to the key.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if not isinstance(x, list) or len(x) != 3:
return None
tonic, pitch, spelling = x
if not isinstance(tonic, int) or not isinstance(pitch, int) or spelling not in ('sharp', 'flat'):
return None
rel = (tonic - pitch) % 12
diatonic = {0: 'do', 2: 're', 4: 'mi', 5: 'fa', 7: 'sol', 9: 'la', 11: 'ti'}
if rel in diatonic:
return diatonic[rel]
if spelling == 'sharp':
return {1: 'di', 3: 'ri', 6: 'fi', 8: 'si', 10: 'li'}[rel]
return {1: 'ra', 3: 'me', 6: 'se', 8: 'le', 10: 'te'}[rel]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([0, 60, 'sharp'], 'do'), ([0, 62, 'flat'], 're'), ([0, 71, 'flat'], 'ti'), ([0, 66, 'sharp'], 'fi'), ([0, 66, 'flat'], 'se'), ([0, 65, 'weird'], None), ([0, 63, None], None), ([3, 1, 'sharp'], 'li')], [([0, 62, 'flat'], 're'), ([0, 67, 'sharp'], 'sol'), ([0, 71, 'flat'], 'ti'), ([0, 61, 'sharp'], 'di'), ([0, 65, 'weird'], None), ([0, 63, None], None), ([9, 57, 'flat'], 'do'), ([3, 1, 'sharp'], 'li')], [([0, 62, 'flat'], 're'), ([0, 67, 'sharp'], 'sol'), ([0, 71, 'flat'], 'ti'), ([0, 61, 'sharp'], 'di'), ([0, 61, 'flat'], 'ra'), ([0, 70, 'flat'], 'te'), ([0, 70, 'sharp'], 'li'), ([3, 1, 'sharp'], 'li')], [([0, 61, 'sharp'], 'di'), ([0, 61, 'flat'], 'ra'), ([0, 70, 'flat'], 'te'), ([0, 70, 'sharp'], 'li'), ([7, 66, 'sharp'], 'ti'), ([7, 64, 'flat'], 'la'), ([7, 60, 'sharp'], 'fa'), ([3, 1, 'sharp'], 'li')], [([0, 61, 'flat'], 'ra'), ([0, 70, 'sharp'], 'li'), ([7, 66, 'sharp'], 'ti'), ([7, 64, 'flat'], 'la'), ([7, 60, 'sharp'], 'fa'), ([2, 64, 'sharp'], 're'), ([2, 63, 'flat'], 'ra'), ([3, 1, 'sharp'], 'li')]]
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 | do | do | Passed |
| oracle 1 | te | re | Failed |
| oracle 2 | ra | ti | Failed |
| oracle 3 | fi | fi | Passed |
| oracle 4 | se | se | Passed |
| oracle 5 | None | None | Passed |
| oracle 6 | None | None | Passed |
| oracle 7 | re | li | Failed |
SHA-256 / 1e89e6f131b1c5d528f07ae2277339b17397332e23b14855451e3d1637880283
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if not isinstance(x, list) or len(x) != 3:
return None
tonic, pitch, spelling = x
if not isinstance(tonic, int) or not isinstance(pitch, int) or spelling not in ('sharp', 'flat'):
return None
rel = abs(pitch - tonic) % 12
diatonic = {0: 'do', 2: 're', 4: 'mi', 5: 'fa', 7: 'sol', 9: 'la', 11: 'ti'}
if rel in diatonic:
return diatonic[rel]
if spelling == 'sharp':
return {1: 'di', 3: 'ri', 6: 'fi', 8: 'si', 10: 'li'}[rel]
return {1: 'ra', 3: 'me', 6: 'se', 8: 'le', 10: 'te'}[rel]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([0, 60, 'sharp'], 'do'), ([0, 62, 'flat'], 're'), ([0, 71, 'flat'], 'ti'), ([0, 66, 'sharp'], 'fi'), ([0, 66, 'flat'], 'se'), ([0, 65, 'weird'], None), ([0, 63, None], None), ([3, 1, 'sharp'], 'li')], [([0, 62, 'flat'], 're'), ([0, 67, 'sharp'], 'sol'), ([0, 71, 'flat'], 'ti'), ([0, 61, 'sharp'], 'di'), ([0, 65, 'weird'], None), ([0, 63, None], None), ([9, 57, 'flat'], 'do'), ([3, 1, 'sharp'], 'li')], [([0, 62, 'flat'], 're'), ([0, 67, 'sharp'], 'sol'), ([0, 71, 'flat'], 'ti'), ([0, 61, 'sharp'], 'di'), ([0, 61, 'flat'], 'ra'), ([0, 70, 'flat'], 'te'), ([0, 70, 'sharp'], 'li'), ([3, 1, 'sharp'], 'li')], [([0, 61, 'sharp'], 'di'), ([0, 61, 'flat'], 'ra'), ([0, 70, 'flat'], 'te'), ([0, 70, 'sharp'], 'li'), ([7, 66, 'sharp'], 'ti'), ([7, 64, 'flat'], 'la'), ([7, 60, 'sharp'], 'fa'), ([3, 1, 'sharp'], 'li')], [([0, 61, 'flat'], 'ra'), ([0, 70, 'sharp'], 'li'), ([7, 66, 'sharp'], 'ti'), ([7, 64, 'flat'], 'la'), ([7, 60, 'sharp'], 'fa'), ([2, 64, 'sharp'], 're'), ([2, 63, 'flat'], 'ra'), ([3, 1, 'sharp'], 'li')]]
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 | do | do | Passed |
| oracle 1 | re | re | Passed |
| oracle 2 | ti | ti | Passed |
| oracle 3 | fi | fi | Passed |
| oracle 4 | se | se | Passed |
| oracle 5 | None | None | Passed |
| oracle 6 | None | None | Passed |
| oracle 7 | re | li | Failed |
SHA-256 / fe136ad037987c0bb7f5d5ec566c02e672c7a26e96b3656b74addf4fb19edaeb
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
if not isinstance(x, list) or len(x) != 3:
return None
tonic, pitch, spelling = x
if not isinstance(tonic, int) or not isinstance(pitch, int) or spelling not in ('sharp', 'flat'):
return None
rel = (pitch - tonic) % 12
diatonic = {0: 'do', 2: 're', 4: 'mi', 5: 'fa', 7: 'sol', 9: 'la', 11: 'ti'}
if rel in diatonic:
return diatonic[rel]
if spelling == 'sharp':
return {1: 'di', 3: 'ri', 6: 'fi', 8: 'si', 10: 'li'}[rel]
return {1: 'ra', 3: 'me', 6: 'se', 8: 'le', 10: 'te'}[rel]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[([0, 60, 'sharp'], 'do'), ([0, 62, 'flat'], 're'), ([0, 71, 'flat'], 'ti'), ([0, 66, 'sharp'], 'fi'), ([0, 66, 'flat'], 'se'), ([0, 65, 'weird'], None), ([0, 63, None], None), ([3, 1, 'sharp'], 'li')], [([0, 62, 'flat'], 're'), ([0, 67, 'sharp'], 'sol'), ([0, 71, 'flat'], 'ti'), ([0, 61, 'sharp'], 'di'), ([0, 65, 'weird'], None), ([0, 63, None], None), ([9, 57, 'flat'], 'do'), ([3, 1, 'sharp'], 'li')], [([0, 62, 'flat'], 're'), ([0, 67, 'sharp'], 'sol'), ([0, 71, 'flat'], 'ti'), ([0, 61, 'sharp'], 'di'), ([0, 61, 'flat'], 'ra'), ([0, 70, 'flat'], 'te'), ([0, 70, 'sharp'], 'li'), ([3, 1, 'sharp'], 'li')], [([0, 61, 'sharp'], 'di'), ([0, 61, 'flat'], 'ra'), ([0, 70, 'flat'], 'te'), ([0, 70, 'sharp'], 'li'), ([7, 66, 'sharp'], 'ti'), ([7, 64, 'flat'], 'la'), ([7, 60, 'sharp'], 'fa'), ([3, 1, 'sharp'], 'li')], [([0, 61, 'flat'], 'ra'), ([0, 70, 'sharp'], 'li'), ([7, 66, 'sharp'], 'ti'), ([7, 64, 'flat'], 'la'), ([7, 60, 'sharp'], 'fa'), ([2, 64, 'sharp'], 're'), ([2, 63, 'flat'], 'ra'), ([3, 1, 'sharp'], 'li')]]
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 | do | do | Passed |
| oracle 1 | re | re | Passed |
| oracle 2 | ti | ti | Passed |
| oracle 3 | fi | fi | Passed |
| oracle 4 | se | se | Passed |
| oracle 5 | None | None | Passed |
| oracle 6 | None | None | Passed |
| oracle 7 | li | li | Passed |
SHA-256 / 3df2e1667528a18b57598ba6019af1dce4c50dd5a4b1e2fdb11146fc83b0f63e
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.847333+00:00.
Case digest / b343b2c00e87827c42c133c58cbc25650a5ae8b6e12dc033fff36323c2a249ad