Skip to content

Instantly share code, notes, and snippets.

@adamchalmers
Created September 17, 2015 14:48
Show Gist options
  • Save adamchalmers/8d7e5e19c9fbfb034d8d to your computer and use it in GitHub Desktop.
Save adamchalmers/8d7e5e19c9fbfb034d8d to your computer and use it in GitHub Desktop.
"""Lists ways to play a certain chord on mandolin.
Example invocation:
$ python mandolin_chords.py Abm
Example output:
The chord Abm has notes Ab, B, Eb
(4, 6, 6, 4) plays B, Ab, Eb, Ab
(8, 6, 6, 7) plays Eb, Ab, Eb, B
(1, 1, 2, 4) plays Ab, Eb, B, Ab
(4, 1, 2, 4) plays B, Eb, B, Ab
(4, 6, 6, 7) plays B, Ab, Eb, B
"""
import itertools
import sys
NOTES = ["A", "Bb", "B", "C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab"]
def note_up(note, dist):
"""Returns the note $dist semitones above base note $note."""
return NOTES[(NOTES.index(note) + dist) % len(NOTES)]
def notes_in_chord(chord):
"""Returns the three notes that make $chord. $chord examples: 'A', 'Cbm'."""
targets = []
if chord[-1] == "m":
assert chord[:-1] in NOTES, "%s isn't a valid note." % chord[:-1]
targets.append(chord[:-1])
targets.append(note_up(targets[0], 3))
else:
assert chord in NOTES, "%s isn't a valid note." % chord
targets.append(chord)
targets.append(note_up(targets[0], 4))
targets.append(note_up(targets[0], 7))
return targets
def fingers_for_chord(chord):
targets = set(notes_in_chord(chord))
options = [] # List of 4 ints, representing which fret to play on each string.
print "The chord %s has notes %s" % (chord, ", ".join(notes_in_chord(chord)))
print
# Loop over every possible combination of frets on each of the four strings
for g, d, a, e in itertools.product(range(16), range(16), range(16), range(16)):
positions = {"G": g, "D": d, "A": a, "E": e}
notes = [note_up(note, i) for note, i in positions.items()]
# If this combination of frets plays the chord, add it to the options list.
if targets == set(notes):
options.append((g, d, a, e))
# Sort the list by the amount your fingers have to stretch.
options.sort(key=lambda option: max(option) - min(option))
for option in options[:5]:
ma, mi = max(option), min(option)
print option, "plays", ", ".join([note_up(n,i) for n,i in zip(["G", "D", "A", "E"], option)])
if __name__ == "__main__":
fingers_for_chord(sys.argv[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment