8
\$\begingroup\$

On a standard 88 key piano, each key has a scientific name.

The first three keys are A0, B♭0, and B0. The keys then proceed through C1, D♭1, D1, E♭1, E1, F1, G♭1, G1, A♭1, A1, B♭1, B1, and start over again at C2. This continues up through B7, and the final key is C8.

Any flat can instead be written as a sharp of the preceding note, e.g. D♭4 can also be written C♯4. If necessary, you can write "D♭4" as "Db4".

Your program should build an ordered sequence (array, list, vector, etc.) containing the key names (as strings, symbols, or some similar data structure) in order.

Program length should be measured in characters, to avoid penalizing people who properly generate ♯ or ♭ rather than # or b. However, Unicode recoding is forbidden.

\$\endgroup\$
4
  • \$\begingroup\$ Here is a previous question that might be useful, as it involves taking note names as input. \$\endgroup\$
    – PhiNotPi
    Commented Jul 28, 2012 at 13:13
  • 3
    \$\begingroup\$ "Unicode recoding is forbidden." Can you edit the question to explain what that means, please? \$\endgroup\$ Commented Jul 30, 2012 at 17:31
  • 1
    \$\begingroup\$ I'd prefer having scoring by bytes, except in the case of ♯ and ♭ which count as one byte each. \$\endgroup\$
    – lirtosiast
    Commented Jun 8, 2015 at 20:35
  • \$\begingroup\$ @Chris: I think it may refer to putting a compressed byte sequence into a Unicode string and just decompressing that. \$\endgroup\$
    – Joey
    Commented Oct 11, 2015 at 14:03

13 Answers 13

6
\$\begingroup\$

Bash shell script (58)

echo {8..0}{B,♭B,A,♭A,G,♭G,F,E,♭E,D,♭D,C}|rev|cut -b40-410

If you do not have rev, you can instead use tac -rs. at a cost of five characters.

Bending the rules, I can subtract thirteen characters (for a score of 45):

echo {8..0}{B,♭B,A,♭A,G,♭G,F,E,♭E,D,♭D,C}|rev

If you really need a bash array, add six characters to the score (for a score of 64):

a=(`echo {8..0}{B,♭B,A,♭A,G,♭G,F,E,♭E,D,♭D,C}|rev|cut -b40-410`)
\$\endgroup\$
1
  • \$\begingroup\$ Can you say more about tac -rs? In GNU coreutils 8.23 (and 6.10), tac -rs (the same as tac --regex --separator) complains about -s missing an argument, and tac -rs "" says it cannot be empty. I don't see a BSD version of tac (though BSD does have rev) to compare to. \$\endgroup\$
    – Adam Katz
    Commented Sep 4, 2015 at 21:43
5
\$\begingroup\$

GolfScript, 60 57 characters

"A BbB C DbD EbE F GbG Ab"88,{1$2<@2>1$+\{8%},@9+12/+}%\;

The snippet produces the following array (see here):

["A0" "Bb0" "B0" "C1" "Db1" "D1" "Eb1" "E1" "F1" "Gb1" "G1" "Ab1" 
"A1" "Bb1" "B1" "C2" "Db2" "D2" "Eb2" "E2" "F2" "Gb2" "G2" "Ab2" 
"A2" "Bb2" "B2" "C3" "Db3" "D3" "Eb3" "E3" "F3" "Gb3" "G3" "Ab3" 
"A3" "Bb3" "B3" "C4" "Db4" "D4" "Eb4" "E4" "F4" "Gb4" "G4" "Ab4" 
"A4" "Bb4" "B4" "C5" "Db5" "D5" "Eb5" "E5" "F5" "Gb5" "G5" "Ab5" 
"A5" "Bb5" "B5" "C6" "Db6" "D6" "Eb6" "E6" "F6" "Gb6" "G6" "Ab6" 
"A6" "Bb6" "B6" "C7" "Db7" "D7" "Eb7" "E7" "F7" "Gb7" "G7" "Ab7" 
"A7" "Bb7" "B7" "C8"]

Edit: Changed from " "/""* to {8%}, to remove space.

\$\endgroup\$
6
  • \$\begingroup\$ I'm kind of intrigued by GolfScript, but a bit confused. Do you know of any tutorials that would help a beginner learn the language? I've tried the tutorial on the official GolfScript web site and looked at several other pages retrieved on Google, but it doesn't make a whole lot of sense. \$\endgroup\$
    – anon
    Commented Jul 28, 2012 at 18:34
  • 1
    \$\begingroup\$ @MikeDtrick There are some Golfscript answers on this website that have explanations about how they work (e.g. codegolf.stackexchange.com/a/6058/3527). However, the best way to learn GS is to start coding something. Even better - try submitting a GS answer and you'll learn from the feedback you'll get :) \$\endgroup\$ Commented Jul 30, 2012 at 15:25
  • 1
    \$\begingroup\$ @MikeDtrick other commented examples: codegolf.stackexchange.com/a/166/3527, codegolf.stackexchange.com/a/172/3527 \$\endgroup\$ Commented Jul 30, 2012 at 15:26
  • \$\begingroup\$ @w0lf Thank you for the resources! \$\endgroup\$
    – anon
    Commented Jul 31, 2012 at 19:41
  • \$\begingroup\$ @w0lf I know this probably isn't the proper place to ask a question, but I'm trying to code an answer for this question in GolfScript. I have a work in progress for the question, but I wanted to get in touch with someone who is skilled in this area. This is just practice, I won't post the answer if someone helps me out. Sorry for being a pest. \$\endgroup\$
    – anon
    Commented Aug 2, 2012 at 0:57
4
\$\begingroup\$

Python 103 96 94 78

[x+y for y in'0123456789'for x in'C Db D Eb E F Gb G Ab A Bb B'.split()][9:97]

updated according to Ev_genus's suggestion

updated according to Howard's suggestion

\$\endgroup\$
4
  • \$\begingroup\$ 94 [x+y for y in'0123456789'for x in['C','Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B']][9:97] \$\endgroup\$
    – Ev_genus
    Commented Jul 28, 2012 at 14:46
  • 1
    \$\begingroup\$ Maybe you can use 'C Db D Eb E F Gb G Ab A Bb B'.split()? \$\endgroup\$
    – Howard
    Commented Jul 28, 2012 at 15:13
  • \$\begingroup\$ omg, really! 78 [x+y for y in'0123456789'for x in'C Db D Eb E F Gb G Ab A Bb B'.split()][9:97] \$\endgroup\$
    – Ev_genus
    Commented Jul 28, 2012 at 15:26
  • \$\begingroup\$ @Howard yeah, i forgot about that \$\endgroup\$
    – Matt
    Commented Jul 28, 2012 at 16:13
4
\$\begingroup\$

Ruby: 75 71 characters

[*?0..?9].product(%w{C Db D Eb E F Gb G Ab A Bb B}).map{|a,b|b+a}[9,88]

(Base idea borrowed from Matt's solution.)

\$\endgroup\$
2
  • 3
    \$\begingroup\$ You can use [*?0..?9] which is a little shorter. \$\endgroup\$
    – Howard
    Commented Jul 28, 2012 at 17:52
  • \$\begingroup\$ I felt that I am missing something there, but I completely forgot the splat. Thank you @Howard. \$\endgroup\$
    – manatwork
    Commented Jul 28, 2012 at 18:35
4
\$\begingroup\$

Mathematica 95 112 100 97 104 chars

Admittedly not very streamlined:

Take[Flatten@Table[# <> ToString@k & /@ 
Partition[Characters[" CDb DEb E FGb GAb ABb B"], 2], {k, 0, 8}], {10, 97}]

The Flat symbol, although it occupies a single character, is transcribed to SO as \[Flat] so I used the letter "b" here.

Output:

keys

Length@%
(* out *)
88
\$\endgroup\$
6
  • \$\begingroup\$ How do you count 95 chars? \$\endgroup\$
    – Matt
    Commented Jul 28, 2012 at 14:45
  • \$\begingroup\$ I forgot to change the character count when I made a correction. It is now correct. (White spaces are there for legibility only, with the exception of those between quotes.) \$\endgroup\$
    – DavidC
    Commented Jul 28, 2012 at 14:57
  • \$\begingroup\$ I get 100 keys from this rather than 88, but I can't find a rule against that, so +1 :-) \$\endgroup\$
    – Mr.Wizard
    Commented Jul 29, 2012 at 14:15
  • \$\begingroup\$ Weird. I too had noticed the 100 keys, but couldn't find an error. \$\endgroup\$
    – DavidC
    Commented Jul 29, 2012 at 14:21
  • \$\begingroup\$ David, your comment made me look at this again. The output is no longer agreeing with the picture you included. It starts "A0", "Bb0", " B0", " C0", and furthermore "C1" doesn't occur until after "Db1", " D1"` etc. (Previously I thought the real keys were in order and there were extras interspersed.) Sorry, but it's broken. :-( \$\endgroup\$
    – Mr.Wizard
    Commented Jul 29, 2012 at 16:10
3
\$\begingroup\$

Mathematica, 88

88 characters for 88 keys :-)

(Row@{#2,#1}&@@@Tuples@{0~Range~8,StringSplit@"C D♭ D E♭ E F G♭ G A♭ A B♭ B"})[[10;;97]]
\$\endgroup\$
3
\$\begingroup\$

J, 81 76 63 62 61 58 characters

_11}.9}.(_2]\,|:9#"0'C DbD EbE F GbG AbA BbB '),.12#1":i.9

Output:

A 0 
Bb0 
B 0 
C 1 
Db1 
D 1 
Eb1 
E 1
...
G 7 
Ab7 
A 7 
Bb7 
B 7 
C 8

Probably a bit of room for shortening here.

\$\endgroup\$
3
\$\begingroup\$

C (92 84 characters)

Not impressive, could be reduced further.

main(i){for(i=9;printf("%c%c%d\n","CDDEEFGGAABB"[i%12]," b b  b b b "[i%12],i/12),++i<97;);}

Using Dietrich Epp's suggestion :

main(i){for(i=9;printf("%.2s%d\n","C DbD EbE F GbG AbA BbB "+2*i%24,i/12),++i<97;);}

It produces the following output :

A 0
Bb0
B 0
C 1
Db1
D 1
Eb1
E 1
F 1
Gb1

... // lines skipped

Eb7
E 7
F 7
Gb7
G 7
Ab7
A 7
Bb7
B 7
C 8
\$\endgroup\$
2
  • \$\begingroup\$ Can shave off 6 characters: main(i){for(i=9;printf("%.2s%d\n","C DbD EbE F GbG AbA BbB "+(i%12)*2,i/12),++i<97;);} \$\endgroup\$ Commented Jul 29, 2012 at 0:02
  • \$\begingroup\$ @DietrichEpp: Thanks! I shaved off two other characters. \$\endgroup\$
    – overcoder
    Commented Jul 30, 2012 at 1:54
2
\$\begingroup\$

C, 105 chars

- failing on size, so ended up aiming for a wtf different solution.

Probably only works on little-endian arch (e.g. intel) due to assumptions of treating int as small string... Assumes C program is called with no arguments, i.e. that w=1

t=12352,f;
main(w){
  t=t&64?t>>8:(w=1+w%7,(w-3)%3?t<<8|98:t+(w==3));
  f=t<<8|w+64;
  puts(&f);
  f-14403?main(w):0;
}

Output:

A0
Bb0
B0
C1
Db1
D1
Eb1
E1
F1
Gb1
G1
Ab1
--lines skipped--
Bb7
B7
C8

Edits

  • -9 chars - removing some brackets and reorganising an 'if'
  • -18 chars - code shuffling, sub 64 from w and pass as main arg
  • -13 chars - Use 't' to carry state rather than 'f'
\$\endgroup\$
1
  • \$\begingroup\$ Really creative answer! \$\endgroup\$ Commented Aug 26, 2019 at 16:45
1
\$\begingroup\$

Haskell: 72 chars

take 88$drop 9[p++show o|o<-[0..],p<-words$"C D♭ D E♭ F F♯ G G♯ A B♭ B"]
\$\endgroup\$
1
\$\begingroup\$

Clojure - 71 chars

(for[c(range 10)n["C""Db""D""Eb""E""F""Gb""G""Ab""A""Bb""B"]](str n c))
\$\endgroup\$
1
\$\begingroup\$

Perl, 57+1

Just dug this up, a nice golfing exercise. Requires -E for say -- counted in score.

say+(CDbDEbEFGbGAbABbB=~/(.b?)/g)[$_%12],$_/12%9for 9..96

\$\endgroup\$
0
\$\begingroup\$

JavaScript (Node.js), 88 bytes

(o=`C,Db,D,Eb,E,F,Gb,G,Ab,A,Bb,B`.split`,`)=>o.flatMap((x,i)=>o.map(n=>n+i)).slice(9,97)

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.