7
\$\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\$
  • \$\begingroup\$ Here is a previous question that might be useful, as it involves taking note names as input. \$\endgroup\$ – PhiNotPi Jul 28 '12 at 13:13
  • 3
    \$\begingroup\$ "Unicode recoding is forbidden." Can you edit the question to explain what that means, please? \$\endgroup\$ – Chris Jester-Young Jul 30 '12 at 17:31
  • \$\begingroup\$ I'd prefer having scoring by bytes, except in the case of ♯ and ♭ which count as one byte each. \$\endgroup\$ – lirtosiast Jun 8 '15 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 Oct 11 '15 at 14:03

12 Answers 12

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\$
  • \$\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 Sep 4 '15 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\$
  • \$\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\$ – Rob Jul 28 '12 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\$ – Cristian Lupascu Jul 30 '12 at 15:25
  • 1
    \$\begingroup\$ @MikeDtrick other commented examples: codegolf.stackexchange.com/a/166/3527, codegolf.stackexchange.com/a/172/3527 \$\endgroup\$ – Cristian Lupascu Jul 30 '12 at 15:26
  • \$\begingroup\$ @w0lf Thank you for the resources! \$\endgroup\$ – Rob Jul 31 '12 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\$ – Rob Aug 2 '12 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\$
  • \$\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 Jul 28 '12 at 14:46
  • 1
    \$\begingroup\$ Maybe you can use 'C Db D Eb E F Gb G Ab A Bb B'.split()? \$\endgroup\$ – Howard Jul 28 '12 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 Jul 28 '12 at 15:26
  • \$\begingroup\$ @Howard yeah, i forgot about that \$\endgroup\$ – Matt Jul 28 '12 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\$
  • 3
    \$\begingroup\$ You can use [*?0..?9] which is a little shorter. \$\endgroup\$ – Howard Jul 28 '12 at 17:52
  • \$\begingroup\$ I felt that I am missing something there, but I completely forgot the splat. Thank you @Howard. \$\endgroup\$ – manatwork Jul 28 '12 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\$
  • \$\begingroup\$ How do you count 95 chars? \$\endgroup\$ – Matt Jul 28 '12 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 Jul 28 '12 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 Jul 29 '12 at 14:15
  • \$\begingroup\$ Weird. I too had noticed the 100 keys, but couldn't find an error. \$\endgroup\$ – DavidC Jul 29 '12 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 Jul 29 '12 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\$
  • \$\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\$ – Dietrich Epp Jul 29 '12 at 0:02
  • \$\begingroup\$ @DietrichEpp: Thanks! I shaved off two other characters. \$\endgroup\$ – overcoder Jul 30 '12 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\$
  • \$\begingroup\$ Really creative answer! \$\endgroup\$ – Krzysztof Szewczyk Aug 26 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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy