Music: what's in this chord?

38

12

Input

The symbol of any triadic chord (see http://en.wikipedia.org/wiki/Chord_(music)#Triads).

Output

The notes constituting the given chord.

Examples

Input: AM Output: A C# E

Input: C#m Output: C# E G#

Input: Db+ Output: C# F A

Input: C0 Output: C D# F#

Bonuses

-50 if you can also deal with seventh chords

-150 for actually playing the sound of the chord

-150 for using printable characters to show how to play the chord on a piano; example for AM:

┌─┬─┬┬─┬─┬─┬─┬┬─┲┱─┬─┬─┲━┱┬─┲━┱─┬─┬┬─┬┬─┬─┐
│ │ ││ │ │ │ ││ ┃┃ │ │ ┃ ┃│ ┃ ┃ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ┃┃ │ │ ┃ ┃│ ┃ ┃ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ┃┃ │ │ ┃ ┃│ ┃ ┃ │ ││ ││ │ │
│ └┬┘└┬┘ │ └┬┘└┲┛┗┱┘ │ ┗┯┛└┲┛ ┃ └┬┘└┬┘└┬┘ │
│  │  │  │  │  ┃  ┃  │  │  ┃  ┃  │  │  │  │
└──┴──┴──┴──┴──┺━━┹──┴──┴──┺━━┹──┴──┴──┴──┘

-100 for using printable characters to show how to play the chord on a guitar; example for AM:

x   o   o   o   o   o
┌───┬───┬───┬───┬───┐
│   │   │   │   │   │
├───┼───┼───┼───┼───┤
│   │   │   │   │   │
├───┼───┼───┼───┼───┤
│   │   █   █   █   │
├───┼───┼───┼───┼───┤
│   │   │   │   │   │

(see https://en.wikipedia.org/wiki/Box-drawing_character)

Rules

  • The result must be a command-line program or script.

  • The input and output can be in any form, as long as it follows a music notation standard.

  • A guitar or piano representation is considered valid if and only if it contains the three (triadic) or four (seventh) required notes and nothing else. The same note can be present several times in the chord.

  • External libraries are not allowed, except for sound generation (in which case the #include, import... directives are not added to the character count).

  • This is code golf, the shortest code wins!

A little bit of music theory...

In modern Western tonal music, every octave is made of twelve successive notes, often noted:

A A# B C C# D D# E F F# G G#

Or:

La La# Si Do Do# Re Re# Mi Fa Fa# Sol Sol#

In this system, we consider that two successive notes (e.g. A and A#, or E and F) are separated by one semitone. Also, the notes are kind of "looping": what immediately follows G# is A.

Pitch constellation

A chord is constituted by a few (2, 3, 4, sometimes more) notes that "sound good together". For instance, triadic chords contain three different notes, and seventh chords contain four different notes.

Let's define the four triadic chords as:

  • Major triad: contains the root of the chord (in this question, the note given as input), the major third for the root (4 semitones higher than the root), and the perfect fifth for the root (7 semitones higher than the root); this can be symbolized 0-4-7

  • Minor triad, symbolized 0-3-7

  • Augmented triad, symbolized 0-4-8

  • Diminished triad, symbolized 0-3-6

Pitch constellations: triads

So for example, if you want to make a C major triad, noted C, CM, Cmaj, you will need three noted:

  • 0: the root, in this case a C
  • 4: the minor third, 4 semitones higher than the root; that's an E
  • 7: the perfect fifth, 7 semitones higher than the root: a G

This is what the 0-4-7, 0-3-7, 0-4-8 and 0-3-6 notations used above mean! For the seventh chords, use the following pattern:

Pitch constallations: seventh chords

That's it for today! Now, amaze me with amazing code... If you have any question, add some comments below.

Mathieu Rodic

Posted 2014-03-24T15:43:57.610

Reputation: 1 170

Just an FYI, the guitar chord you have as AM is more like Bb... – Beta Decay – 2017-05-28T07:43:18.477

Kind-of the inverse of this older question.

– Peter Taylor – 2014-03-24T15:50:31.567

Yes, I found it too when checking for duplicates... but even if both questions are about chords, the way to the solution is quite different! – Mathieu Rodic – 2014-03-24T15:54:35.487

1It might be worth adding an explanation including the formulas for the chords in integer notation for non musicians. Integer notation refers to everything in semitones. Major chord (Example AM): 0,4,7. Minor chord (example C#m): 0,3,7. C diminished (Example Co, or as you call it C0) 0,3,6 (note that the correct representation is C Eb Gb, but for this challenge I guess we can assume both this and C D# F# are acceptable.) The formula for an augmented chord (Example Db+) is 0,4,8 and your example is wrong as it doesn't even contain a Db. As written it is a B+ which is equivalent to a D#+ or G+ – Level River St – 2014-03-24T17:12:26.417

Also, when you consider adding a seventh to all of these triads, there are a bewildering number of possibilities. Can we assume the challenge is limited to the dominant seventh? (formula 0,4,7,10) Example G B D F. – Level River St – 2014-03-24T17:14:43.503

Finally, does the chord inversion on the piano have to be one with the root as the lowest note? I assume any valid inversion is acceptable on the guitar, as the "standard" inversion on the piano is often impossible on the guitar. Note that one of the most inversions for C7 on the guitar does not even contain a G: http://music.stackexchange.com/questions/12205/why-does-the-c7-chord-on-guitar-omit-the-g-note-5th-in-open-position.

– Level River St – 2014-03-24T17:20:15.063

3Also, shortest code will result from use of the same chord shape for all guitar chords of the same type, barred. So Ab will be an A shape barred at the 11th fret. Is it Ok to put a number or do we have to draw 11 frets? All in all, it's a lot of things to think about. You may want to simplify the bonuses. – Level River St – 2014-03-24T17:29:11.693

By the way, I do like the question :-) – Level River St – 2014-03-24T17:38:36.537

@steveverrill: a lot of constructive comments... I am editing the question :) – Mathieu Rodic – 2014-03-24T20:22:18.277

@steveverrill: phew! I added some precisions and a bit of music theory. The result is terribly long, and I'm not sure it will be of much help for music newbies... – Mathieu Rodic – 2014-03-24T21:34:03.633

1Hmm.. your augmented chord is still wrong. C# is enharmonic to Db, but Db+ is Db F A there's no D# or G in there. That's perhaps a little more theory than necessary, the formulas were the important part. If you really want to include all eight of the seventh chords listed in wikipedia you should specify the input. I assume the ascii-art output of piano and guitar is flexible. – Level River St – 2014-03-24T22:04:39.450

Oops indeed. Edited. – Mathieu Rodic – 2014-03-24T22:09:49.267

"The input and output can be in any form, as long as it follows a music notation standard." How much are we allowed to restrict it? Can we say only C# is accepted and neglect the equivalent Db, or vice versa? Can we use/require h in place of #? Do we have to support both of CM Cmaj or just one? – algorithmshark – 2014-03-24T22:50:02.377

@algorithmshark: it means you can follow the standard(s) of your choice, as long as you remain consistent. – Mathieu Rodic – 2014-03-24T22:53:21.037

What do you think about including F# in the tonal scale? – tomsmeding – 2014-03-25T07:03:34.850

3I feel like I've learned more about music theory here than I've learned from lessons. – Kevin Evans – 2014-03-28T22:37:24.020

4The coolest problem on this site ! – Ray – 2014-03-31T17:16:53.287

You could also add a bonus for accepting a key, major/minor/augmented/diminished, and a figured bass to determine the chord. – Justin – 2014-04-03T20:22:11.130

Answers

5

BBC BASIC

Emulator at bbcbasic.co.uk

Rev 1, 340 - 150 keyboard - 150 playing = 40

Here's the latest version, in which I managed to include the following enhancements while lengthening by only a few more characters.

Input can be edited comfortably on the screen before pressing return (I was using GET$ before to get single keypresses, because BBC Basic does not let you access a single character from a string as if the string was an array. Now I use the rather bulky MID$ function to extract a string of one character from within the string.

Both sides of keyboard displayed as well as the full line between E and F.

To compensate for the characters added by the above, I rearranged the program to eliminate unnecessary print statements, and deleted some white space which at first sight looked like it couldnt be deleted. IN BBC Basic all built in functions are reserved words, and you can put a variable name right before them with no space in between. Variable names are not allowed to start with a reserved word. In order to make the program less confusing to read I changed all variables to lower case.

Although the presentation looks much better, the following program is actually fully golfed already. (See correction below.) Generally newlines and colons are interchangeable, except when an IF statement is used. In that case all statements on the same line (separated by colons) with be executed conditionally. Statements after the newline are not controlled by the IF and will always be executed.

Program rev 1 340 characters

  a$="C#D#EF#G#A#B0Mm+"
  INPUTx$
  r=INSTR(a$,LEFT$(x$,1))-1
  c=INSTR(a$,MID$(x$,2,1))
  IFc=2c=INSTR(a$,MID$(x$,3)):r=r+1
  t=(r+4-c MOD2)MOD12
  f=(r+c DIV2)MOD12
  v=1
  FORn=-1TO11
  c=1-(n<0ORn=4ORn=11)*5
  b$=MID$(a$,n+1,1)
  IFb$="#"c=11:b$=MID$(a$,n,1)+b$
  c$=MID$("   _______--|__",c,5)
  IFr=n ORt=n ORf=n c$=c$+b$:SOUNDv,-15,100+n*4,99:v=v+1
  PRINTc$
  NEXT

CORRECTION: RT Russell's BBC BASIC for Windows allows you to eliminate some newlines and colons, bringing the total down to 327, see below. Also it tokenises the keywords into single characters before saving, bringing it down to 279.

  a$="C#D#EF#G#A#B0Mm+"INPUTx$
  r=INSTR(a$,LEFT$(x$,1))-1c=INSTR(a$,MID$(x$,2,1))IFc=2c=INSTR(a$,MID$(x$,3))r=r+1
  t=(r+4-c MOD2)MOD12f=(r+c DIV2)MOD12v=1FORn=-1TO11c=1-(n<0ORn=4ORn=11)*5b$=MID$(a$,n+1,1)IFb$="#"c=11b$=MID$(a$,n,1)+b$
  c$=MID$("   _______--|__",c,5)IFr=n ORt=n ORf=n c$=c$+b$SOUNDv,-15,100+n*4,99v=v+1
  PRINTc$
  NEXT

Output rev 1

enter image description here

Rev 0, 337 - 150 keyboard - 150 playing = 37

A$="C#D#EF#G#A#B0Mm+":X$=GET$:R=INSTR(A$,X$)-1:X$=GET$:IF X$="#"R=R+1:X$=GET$
C=INSTR(A$,X$):T=(R+4-C MOD2)MOD12:F=(R+C DIV2)MOD12:V=1:PRINT"______"
FORN=0 TO 11
C=1-(N=4)*12:B$=MID$(A$,N+1,1): IF B$="#" C=7: B$=MID$(A$,N,1)+B$
PRINT MID$("    __---|________",C,6);:IF(R-N)*(T-N)*(F-N)=0 PRINT B$;:SOUND V,-15,100+N*4,99:V=V+1
PRINT
NEXT

This is a similar concept to my Arduino answer, but I always knew I could beat that byte count with BBC basic. Only recognises sharps, but considers B# invalid,you must put C. This could be fixed if it was really considered important.

I abandoned the idea of guitar and concentrated on improving the keyboard. It now runs from C to B, and I've added in the left side of the keyboard and the line between E and F. That costs 28 characters. The right hand side wouldn't be much more.

Here's some sample output, an A# diminished chord (which has a pretty freaky sound in this inversion) and a B major chord. Note that the input is not echoed to the screen. As per the Arduino answer, turn the screen anticlockwise to view.

enter image description here

Ungolfed version

A$="C#D#EF#G#A#B0Mm+"                              :REM Note names and chord type names fit very conveniently in the same string.
X$=GET$                                            :REM Get a character 
R=INSTR(A$,X$)-1                                   :REM Root note = position of that char in A$. INSTR starts counting at 1, but we want 0, so subtract.
X$=GET$                                            :REM If the root note is natural, the next character will be the chord type. But...
IF X$="#"R=R+1:X$=GET$                             :REM If this char is # we need to increment the root, and get another char for chord type. 
C=INSTR(A$,X$)                                     :REM C encodes for chord type
T=(R+4-C MOD2)MOD12                                :REM even C means major third, odd C means minor third
F=(R+C DIV2)MOD12                                  :REM "Mm" gives C=14,15 meaning C DIV2=7 (perfect fifth.) C=13,16 give diminished and augmented: 6,8.
V=1                                                :REM V is the sound channel number ("voice")                             
PRINT"______"                                      :REM left side of keyboard for cosmetic reasons
FORN=0 TO 11                                       :REM at the start of each iteration initialise C to 1, to point to the 4 spaces/2 underscores in the string below for drawing white notes. 
  C=1-(N=4)*12                                     :REM if the note is E, add 12 so it points to the 6 underscores to draw the line between E and F. 
  B$=MID$(A$,N+1,1)                                :REM load B$ with the name of the current note.
  IF B$="#" C=7: B$=MID$(A$,N,1)+B$                :REM if the character encountered is a sharp, update C to point the characters for drawing a sharp. Find the previous character in A$ and join it to the beginning of B$ to complete the note name.
  PRINT MID$("    __---|________",C,6);            :REM print the key (6 characters.)
  IF(R-N)*(T-N)*(F-N)=0 PRINT B$;:SOUND V,-15,100+N*4,99:V=V+1  :REM if N is equal to R,T or F, print the note name beside the key, play the note and increment the channel number for the next note.  
  PRINT                                            :REM print a carriage return. It may be possible to golf this line out.
NEXT

Level River St

Posted 2014-03-24T15:43:57.610

Reputation: 22 049

How is the program supposed to be used from command line? (I installed BBC BASIC on my Ubuntu machine) – Mathieu Rodic – 2014-04-03T14:27:46.647

Wow, I didn't know there was a version of BBC basic for Ubuntu. I can't find one on the site I got my emulator from, and I don't use Ubuntu. Original BBC basic only had one program in memory at a time so you typed RUN. With the emulator I use you have to start the emulator environment then it runs within it. It has a text editor, then you click to run, then when the program terminates you can either type RUN to run the program again, or type individual Basic commands within the environment. You can produce a command-line executable with my emulator, but only if you buy the full version. – Level River St – 2014-04-03T17:32:27.690

If you want to test the program, the best way I could help you is if you could find a Windows machine and download the exact version I'm using. Alternatively, if you could tell me where you got your Ubuntu version from I could have a little read of that. – Level River St – 2014-04-03T17:48:24.700

BBC Basic runs on Linux too, they provide many distributions on their home page depending on the host OS. I just didn't manage to get the program running, neither from passing the code or pasting it in the prompt... – Mathieu Rodic – 2014-04-03T21:27:09.460

I just downloaded Napoleon Brandy Basic, and it is indeed, difficult to get started! You need save the code as text file called chords.nap, then type LOAD"chords.nap" at the command prompt. It adds line numbers to the code (more authentic to the original BBC Basic, would add a few more characters) Then you type RUN and the program crashes at the line with the SOUND statement in it, with the error message "Unsupported Basic V feature found." You could actually write a serious program with RT Russell's implementation if you really wanted to. But with Brandy basic I wouldn't even think about it. – Level River St – 2014-04-03T22:27:44.143

In conclusion, This is the only one at bbcbasic.co.uk that might work with Linux AND sound: http://appdb.winehq.org/objectManager.php?sClass=version&iId=21754 But I just realised the point of Wine it's to make a Windows application run on Linux. And INKEY$ doesn't work, so GET$ may not work either (the new version does not use either.) It's a pity, because I know you like my post and I would like you to hear it. Here's the full link for the Windows version http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

– Level River St – 2014-04-03T22:47:13.350

Ok, I got it working with Wine. The program works pretty well, and the sounds are alright (event though the square signals are horrendous). Although the actual length in bytes is 337 (newlines count), this one definitely looks like a winner! – Mathieu Rodic – 2014-04-04T07:12:06.653

@MathieuRodic Your byte count of 337 for Rev0 is correct, the program I used to count didn't count the newlines. For Rev1 it was actually 348, not 337. But I have modified two lines and now it is down to 340 (I was trying to be too clever with the way I combined conditions, a simple OR and elimination of whitespace is shorter.) I found it's also possible to delete some newlines/colons but I added that as a note rather than claiming it in the title. I prefer to win with well presented code if possible. Thanks for going to the trouble of testing the program! – Level River St – 2014-04-05T08:41:21.043

Something to try: Change INPUTx$ for READ x$, and add a line at the bottom: DATA CM,GM,Am,FM. Put the whole program inside a FOR loop, and add a line RUN at the end so it restarts itself. Now it plays a 4-chord turnaround continuously (the screen gets a little out of sync with the sound.) Adjust the 99 in the SOUND statement for the tempo desired. – Level River St – 2014-04-05T08:52:02.113

8

As you can tell, I didn't try to golf this at all. I'm a music geek, and a pet peeve of mine is when people write things using the wrong enharmonics (e.g. saying that a C diminished chord is C D# F# instead of C Eb Gb), so I wrote this program that gets the enharmonics right. It does so by representing each note as the number of perfect fifths above F.

For what it's worth, if you want to distinguish enharmonics, any musical interval can be represented nicely in a computer program as a number of perfect fifths and a number of octaves. An augmented fourth, for example, is 6 perfect fifths and -3 octaves, and a diminished fifth is -6 perfect fifths and 4 octaves.

Haskell, 441 characters

import Data.List

notes = "FCGDAEB"

fromNum x = [notes !! (mod x 7)] ++ if x < 0 then replicate (-(div x 7)) 'b' else replicate (div x 7) '#'

toNum (x:xs) = y + 7 * if isPrefixOf "b" xs then -length xs else length xs
    where Just y = elemIndex x notes

chord xs = unwords . map (fromNum . \x -> toNum (init xs) + x) $ case last xs of 'A' -> [0,4,8]; 'M' -> [0,4,1]; 'm' -> [0,-3,1]; 'd' -> [0,-3,-6]

main = getLine >>= putStrLn . chord

Some example invocations:

jaspers:junk tswett$ ./chord
AM
A C# E
jaspers:junk tswett$ ./chord
C#m
C# E G#
jaspers:junk tswett$ ./chord
DbA
Db F A
jaspers:junk tswett$ ./chord
Cd
C Eb Gb
jaspers:junk tswett$ ./chord
A#M
A# C## E#
jaspers:junk tswett$ ./chord
Dbm
Db Fb Ab

Tanner Swett

Posted 2014-03-24T15:43:57.610

Reputation: 531

5

Arduino

Input/output is sent to / received from the Arduino via a COM port. A user can interact with this via a terminal, or the serial monitor in the Arduino IDE. As you may have guessed from my choice of platform, I am planning to include the actual playing of the chord (though I haven't done it yet.)

I have tackled the keyboard bonus successfully, and I have tried to tackle the guitar, with limited success.

The chord box comes in at 130 bytes, which is too long to be worth it. Therefore I have tried another way, just printing the fret numbers Tab style. Currently this is 81 bytes for a bonus of 81-100=-19. If this approach is deemed valid I can try and improve on it.

The chords used are all D-type shapes with the root on the 2nd string, fifth on the 3rd string, and third on the 1st and 4th strings. The 5th and 6th strings are not used and I mark this with X's on the right of the chord box (the left would be more usual, but examples marked on the right can be found.)

Because the program considers F to be the lowest note (for compatability with the keyboard while avoiding excessively high frets with this chord shape) the highest chord is an E (with root on the 17th fret.) See example output.

The keyboard is more successful in terms of golfing. It runs from F-E rather than C-B for the reasons described above. It must be viewed by turning the screen 90% anticlockwise, when you can clearly see the outlines of the black notes, and the demarcation between the white notes with ---. The line between B an C could be extended with some ____ for a few more bytes.

I will try playing the notes next. This will be interesting because, although I believe the Arduino Uno has 3 internal timers, only one note at a time can be played using the built in tone command. There is an external library function which uses all the hardware timers (which will mess up the serial, but it won't be needed at that stage anyway.) Alternatively I may try to produce the tones in softare.

If I am successful with that, I will golf it down but I don't think it will be the overall winner.

Ungolfed code

String p="F#G#A#BC#D#E -Mm+",y,d[]=
{"    ","---|"},n="\n";

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(99999);
}

void loop(){
  char x[9]; int r,t,f,i,c=1;
  Serial.readBytesUntil(13,x,9);
  Serial.println(x);  
  r=p.indexOf(x[0]);
  if (x[1]==35|x[1]==98){c=2;r+=x[1]==35?1:-1;}
  f=p.indexOf(x[c])/2;
  t=4-p.indexOf(x[c])%2;

  //chord box
  y=n;for(i=24;i--;)y+=d[1]+(i%4?"":" \n");
  y[89]=y[107]='X'; y[t*4-10]=y[t*4+52]=y[f*4+14]=y[28]='O';
  Serial.print("\t "+String(r+6)+y);

  f+=r;t+=r;

  //tab style
  Serial.println(String(t+1)+n+String(r+6)+n
  +String(f-2)+n+String(t+3)+"\nX\nX\n");

  f%=12;t%=12;

  //piano
  for(i=0;i<12;i++){
    c=0;
    y=String(p[i]);
    if(y=="#") {c=1;y=p[i-1]+y;}      
    Serial.println(d[c]+"__"+((r-i&&t-i&&f-i)?"":y));
  }  
}

Sample output The lower the spacing between the lines of text, the better this looks. Therefore it looks great when I am actually editing the post, but horrible in the grey box after posting. Instead I've posted a screenshot of the Arduino serial monitor which is of intermediate line spacing (and hence display quality.)

enter image description here

Level River St

Posted 2014-03-24T15:43:57.610

Reputation: 22 049

Can't wait for the actual sound! – Mathieu Rodic – 2014-03-31T07:20:40.413

The notes for EM are correct (E G# B), but they aren't aligned correctly on your keyboard. It looks like you're on the right track though! – Cameron Tinker – 2014-03-31T15:36:18.053

@CameronTinker Please tilt your screen 90 deg anticlockwise and look again. Note that the keyboard runs from F to E, not from C to B for the reasons described in my post. Choosing F as the internal "zero note" was a compromise for both guitar and keyboard output. There are 3 black notes on the left, 2 on the right and the output notes are correctly aligned. Extending the division between B and C would make it clearer, but would cost about 20 extra bytes. Crude it is, but I still think my keyboard is more readable than Pandubear's. – Level River St – 2014-03-31T17:30:51.637

I don't know how I missed that! Sorry about that. I'm a pianist and my first inclination when I saw this was that the keyboard didn't look right ;). – Cameron Tinker – 2014-03-31T17:37:06.657

@MathieuRodic I've got sounds out of the Arduino now, but they are so poor I'm not sure I'd call them a recognisable chord. I will have another try, but there are a few things happening with the Arduino that I don't understand. Anyway I just posted an answer in BBC Basic with keyboard and sound that's looking much better. So I will update this post later – Level River St – 2014-04-03T01:29:08.943

4

Python3 - 315 char

First time in codegolf! Only supports minor, major, diminished and augmented chords right now.

z=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];y=[1,2,4,5,6]
def q(a):print(z[a%12])
a=input();k=(ord(a[0])+3)%7;j=k;m=4;s=0;f=7;
for i in y:
    if(k>=i):j+=1
if('#'in a):j+=1
if('b'in a):j-=1
if('m'in a or'0'in a):m=3
if('+'in a or"aug"in a):f=8
if('0'in a or"dim"in a):f=6;m=3
if('ma'in a):m=4
q(j);q(j+m);q(j+f);

John

Posted 2014-03-24T15:43:57.610

Reputation: 41

2Use 'C C# D D# E F F# G G# A A# B'.split(' ') instead of your literal array to save some bytes. – wchargin – 2014-03-25T00:36:05.967

2if('#'in a):j+=1 -> if'#'in a:j+=1 = 2 chars less for every statement. Also changing y to a range() expression saves something too. Welcome! (and remember that newlines also count ;)) – gcq – 2014-03-25T01:17:17.527

2@wch More bytes can be saved with 'C C# D D# E F F# G G# A A# B'.split() ;) – undergroundmonorail – 2014-03-25T01:25:10.110

1How did you count your score? I think you have to count new lines as one char each as well. By the way, since this answer works only in Python3, I'll edit your answer to explicitly state that. Also, instead of using y to store [1,2,4,5,6], why don't you just skip the y and replace line 4 with for i in[1,2,4,5,6]:? Anyway, welcome to codegolf and I hope you have fun here. – user12205 – 2014-03-25T03:56:37.290

1You can also save 3 more chars by indenting with only one space instead of four in line 5. – user12205 – 2014-03-25T04:03:00.943

4

Python 506(unicode as 1 char)-150(sound)-150(keyboard) = 206

For sound playing, it uses pygame.midi. Note that the pygame.midi.get_default_output_id() method don't work very well. So you may try changing the line o=Output(get_default_output_id()) to o=Output(1), o=Output(2), etc. Usually the correct value is between 0 and 5.

c=input()
s='C D EF G A B'.index(c[0])+{'#':1,'b':-1,'':0}[c[1:-1]]
m='0mM+'.index(c[-1])
t=s+3+m//2
R=[list(x)for x in['┌─'+'─┬─'*13+'─┐']+['│'+'  │'*14]*5+['└─'+'─┴─'*13+'─┘']]
i=3
for d in[3,6,3,3,6]*2:q=slice(i-1,i+2);R[0][q]='┬─┬';R[1][q]=R[2][q]=R[3][q]='│ │';R[4][q]='└┬┘';i+=d
X=[2]+[1,2,1,2,3,1,2,1,2,1,2,3]*2
from pygame.midi import*
init()
o=Output(get_default_output_id())
for s in[s,t,t+3+m%2]:R[[5,3][s%12 in[1,3,6,8,10]]][sum(X[:s+1])]='o';o.note_on(s+60,127,1)
for r in R:print(''.join(r))

Results

goooolf> python chords2.py
CM
┌─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┬─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┐
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │
│ o│  │ o│  │ o│  │  │  │  │  │  │  │  │  │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
goooolf> python chords2.py
Cm
┌─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┬─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┐
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││o│ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │
│ o│  │  │  │ o│  │  │  │  │  │  │  │  │  │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
goooolf> python chords2.py
Dm
┌─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┬─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┐
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │
│  │ o│  │ o│  │ o│  │  │  │  │  │  │  │  │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
goooolf> python chords2.py
D+
┌─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┬─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┐
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │o││ ││o│ │ │ ││ │ │ │ ││ ││ │ │
│ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │
│  │ o│  │  │  │  │  │  │  │  │  │  │  │  │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
G+
┌─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┬─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┐
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││o│ │ │ ││ ││ │ │
│ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │
│  │  │  │  │ o│  │ o│  │  │  │  │  │  │  │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
goooolf> python chords2.py
Am
┌─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┬─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┐
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │
│  │  │  │  │  │ o│  │ o│  │ o│  │  │  │  │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
goooolf> python chords2.py
C#0
┌─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┬─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┐
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │o││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │
│  │  │ o│  │ o│  │  │  │  │  │  │  │  │  │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
goooolf> python chords2.py
EbM
┌─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┬─┬─┬┬─┬─┬─┬─┬┬─┬┬─┬─┐
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││ │ │ │ ││ ││ │ │ │ ││ │ │ │ ││ ││ │ │
│ │ ││o│ │ │ ││ ││o│ │ │ ││ │ │ │ ││ ││ │ │
│ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │ └┬┘└┬┘ │ └┬┘└┬┘└┬┘ │
│  │  │  │  │ o│  │  │  │  │  │  │  │  │  │
└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘

Ray

Posted 2014-03-24T15:43:57.610

Reputation: 1 946

3

J - 82 char

Self-contained, reads from console input. If you need stdin, change the final 1 to a 3. Claiming no bonuses, and only covering the triads.

+/&(0 3 6++/\_3{.#:'0mM+'i.{:e)&.((,~C`Db`D`Eb`E`F`Gb`G`Ab`A`Bb`B)i.;:)}:e=.1!:1]1

Instead of a sharp note e.g. C# you must use the equivalent flat name Db. (Correcting for this would inflate the code by more than a bit.) The four types of chords are 0 for diminishing, m for minor, M for major, and + for augmented.

The logic is as follows: we use the last character to add an offset to the base 0-3-6, which selects the kind of third and fifth. Meanwhile, we use the note to find where in the scale to pull the notes from. The ;: both makes the note compatible with indexing into the scale at the start, and later (by &.) turns the pulled notes into a space separated string.

Example usage:

   +/&(0 3 6++/\_3{.#:'0mM+'i.{:e)&.((,~C`Db`D`Eb`E`F`Gb`G`Ab`A`Bb`B)i.;:)}:e=.1!:1]1
AM
A Ch E
   +/&(0 3 6++/\_3{.#:'0mM+'i.{:e)&.((,~C`Db`D`Eb`E`F`Gb`G`Ab`A`Bb`B)i.;:)}:e=.1!:1]1
Ab0
Ab B D
   +/&(0 3 6++/\_3{.#:'0mM+'i.{:e)&.((,~C`Db`D`Eb`E`F`Gb`G`Ab`A`Bb`B)i.;:)}:e=.1!:1]1
B+
B Eb G
   +/&(0 3 6++/\_3{.#:'0mM+'i.{:e)&.((,~C`Db`D`Eb`E`F`Gb`G`Ab`A`Bb`B)i.;:)}:e=.1!:1]1
Em
E G B

algorithmshark

Posted 2014-03-24T15:43:57.610

Reputation: 8 144

Does the suffix 'h' follow one of the "music notation standards"? – Mathieu Rodic – 2014-03-25T01:18:16.770

@MathieuRodic I suppose it's a grey area, so I bumped them all up to flats. No change in functionality. Don't know why I didn't do this earlier. – algorithmshark – 2014-03-25T01:24:39.607

2

Javascript, 224 char

n=prompt();a="A0A#0B0C0C#0D0D#0E0F0F#0G0G#".split(0);x=1;r=a.indexOf(n[0]);n[1]=="#"&&(r++,x++);n[1]=="b"&&(r--,x++);s=r+4;l=r+7;(n[x]=="m"||n[x]==0)&&s++;s%=12;n[x]=="+"&&l++;n[x]==0&&l--;l%=12;alert(a[r]+" "+a[s]+" "+a[l])

This is my first code golf. I think it can be shorter, but I can't find any bytes to save.

Supports major, m for minor, 0 for diminished, + for augmented, or 37 more bytes for dim, aug.

Snack

Posted 2014-03-24T15:43:57.610

Reputation: 2 142

n[m]==0 can be simply !n[m]. Same applies at another place. Total you can cut off 6 chars easily. – Gaurang Tandon – 2014-03-25T15:52:11.530

@GaurangTandon Since n is string, n[m]==0 will cast 0 to "0", so it equals to n[m]=="0". "0" == 0 is true, but !"0" is false. – Snack – 2014-03-26T02:11:36.397

I was just pointing out because I got the same output when I inputted AM. I might be wrong also. – Gaurang Tandon – 2014-03-26T05:59:43.343

2

Python (143 134 chars)

n,a='A A# B C C# D D# E F F# G G#'.split(),input();m,i=ord(a[-1])-42,n.index(a[:-1])
print(n[i],n[(i+4-m//2)%12],n[(i-4+(-m//2))%12]) 

My first golf challenge :), don't know if some more bytes can be shaved off.
The notation used here is * aug / + maj / , min / - dim
I deserve a bonus point for having the constant 42 in the code :P

LemonBoy

Posted 2014-03-24T15:43:57.610

Reputation: 339

You can gain a few bytes like this: n,q,a='A A# B C C# D D# E F F# G G#'.split(),[4,4,3,3],input();m,i=ord(a[-1])-42,n.index(a[:-1]) – Mathieu Rodic – 2014-03-30T22:18:45.883

1

Python 3: 257 - 150 = 107

Just 25 chars too long to beat the J solution! Oh well. There are some neat ideas here, I think.

I='AaBCcDdEFfGg'*2
Q='0123456789.,'*2
K="""-1#_2
-,#_0
-9#_.
____8
-6#_7
-4#_5
____3"""
r,*R,q=input()
r=I.find(r)+bool(R)
p=str.replace
for x in[0]+[8,4,7,3,6]['+Mm0'.find(q):][:2]:K=p(K,Q[x+r],I[x+r].upper())
for x in Q:K=p(K,x,' ')
print(p(K,' #','  '))

Input is like the examples, though you must use sharp names instead of flat names. (e.g. Gb must be F#)

Output is a single octave of a piano, seen from above and to the left, with note names superimposed. Should be just a tiny stretch of the imagination.

$ echo C#m | python3 chords.py
-  _ 
-G#_ 
-  _ 
____ 
-  _E
-C#_ 
____ 

pandubear

Posted 2014-03-24T15:43:57.610

Reputation: 357

Nice job! Although, I don't see the notes to play in the output? For CM, we should be able to read C E G... – Mathieu Rodic – 2014-03-28T12:53:28.630

Oh, I misinterpreted the question I suppose. Let's see if I can work that in... – pandubear – 2014-03-28T16:27:05.930

Fixed! Too long... ): – pandubear – 2014-03-28T18:21:57.097

Can't you replace bool(R) with R|0? – Mathieu Rodic – 2014-03-31T07:19:46.367

Nah, the point is that R is a list and bool(R) is 1 (true) if nonempty, and 0 (false) if empty. The | operator doesn't work with lists... – pandubear – 2014-03-31T07:25:54.930

The output looks ugly... – Ray – 2014-04-01T13:34:01.993

@Ray to be fair, he was trying to beat the golf score of an answer in J. He gave the best shot at what he was trying to do and unfortunately he failed. If the downvote is yours, i don't think he deserves it. I am upvoting because his keyboard inspired mine. – Level River St – 2014-04-02T20:38:41.460

1

Scala 537 chars - 50

import java.util.Scanner
object C extends App{
val c=Map("M"->145,"m"->137,"+"->273,"0"->73,"7"->1169,"M7"->2193,"m7"->1161,"Mm7"->2185,"+7"->1297,"+M7"->2321,"07"->585,"7b5"->1097)
val n=List("A","A#","B","C","C#","D","D#","E","F","F#","G","G#")
val o=List("","Bb","Cb","B#","Db","","Eb","Fb","E#","Gb","","Ab")
val s=new Scanner(System.in).nextLine
val v=s indexWhere{c=>c!='#'&&c!='b'&&(c<'A'||c>'G')}
val (u,m)=s splitAt v
val x=n.indexOf(u)max o.indexOf(u)
val k=c(m)
for(i<-0 to 11)if((k&(1<<i))!=0)print(n((i+x)%12)+" ")
println}

bb94

Posted 2014-03-24T15:43:57.610

Reputation: 1 831

0

Haskell, 273 chars

n(s,a)="CCDDEFFGGAABB"!!(s+1-a):["b#"!!a|" b b  b b b "!!s/=' ']
t p=[(s,a)|s<-[11,10..0],a<-[0,1],n(s,a)==p]!!0
m(s,d)=n(mod s 12,d-3)
c q=[n(a,x),m(a+d,d),m(a+d+e,e)]where
 (a,x)=t$init q;f=lookup(last q).zip"0mM+";Just d=f[3,3,4,4];Just e=f[3,4,3,4]
main=print.c=<<getLine

Results

C0 ->["C","Eb","Gb"]   Cm ->["C","Eb","G"]    CM ->["C","E","G"]     C+ ->["C","E","G#"]    
C#0->["C#","F","G"]    C#m->["C#","F","G#"]   C#M->["C#","F","Ab"]   C#+->["C#","F","A"]    
D0 ->["D","F","Ab"]    Dm ->["D","F","A"]     DM ->["D","F#","A"]    D+ ->["D","F#","A#"]   
D#0->["D#","Gb","A"]   D#m->["D#","Gb","A#"]  D#M->["D#","G","Bb"]   D#+->["D#","G","B"]    
E0 ->["E","G","Bb"]    Em ->["E","G","B"]     EM ->["E","G#","B"]    E+ ->["E","G#","C"]    
F0 ->["F","Ab","B"]    Fm ->["F","Ab","C"]    FM ->["F","A","C"]     F+ ->["F","A","C#"]    
F#0->["F#","A","C"]    F#m->["F#","A","C#"]   F#M->["F#","A#","Db"]  F#+->["F#","A#","D"]   
G0 ->["G","Bb","Db"]   Gm ->["G","Bb","D"]    GM ->["G","B","D"]     G+ ->["G","B","D#"]    
G#0->["G#","B","D"]    G#m->["G#","B","D#"]   G#M->["G#","C","Eb"]   G#+->["G#","C","E"]    
A0 ->["A","C","Eb"]    Am ->["A","C","E"]     AM ->["A","C#","F"]    A+ ->["A","C#","F"]    
A#0->["A#","Db","F"]   A#m->["A#","Db","F"]   A#M->["A#","D","F"]    A#+->["A#","D","F#"]   
B0 ->["B","D","F"]     Bm ->["B","D","F#"]    BM ->["B","D#","Gb"]   B+ ->["B","D#","G"]    

Ray

Posted 2014-03-24T15:43:57.610

Reputation: 1 946