20
\$\begingroup\$

Oh no! I have a theory test soon and I don't remember the scales yet! Help me remember my major scales by printing the following:

7♯ - C♯ D♯ E♯ F♯ G♯ A♯ B♯ C♯
6♯ - F♯ G♯ A♯ B  C♯ D♯ E♯ F♯
5♯ - B  C♯ D♯ E  F♯ G♯ A♯ B
4♯ - E  F♯ G♯ A  B  C♯ D♯ E
3♯ - A  B  C♯ D  E  F♯ G♯ A
2♯ - D  E  F♯ G  A  B  C♯ D
1♯ - G  A  B  C  D  E  F♯ G
0  - C  D  E  F  G  A  B  C
1♭ - F  G  A  B♭ C  D  E  F
2♭ - B♭ C  D  E♭ F  G  A  B♭
3♭ - E♭ F  G  A♭ B♭ C  D  E♭
4♭ - A♭ B♭ C  D♭ E♭ F  G  A♭
5♭ - D♭ E♭ F  G♭ A♭ B♭ C  D♭
6♭ - G♭ A♭ B♭ C♭ D♭ E♭ F  G♭
7♭ - C♭ D♭ E♭ F♭ G♭ A♭ B♭ C♭

This is code-golf, so shortest code wins. You may use # and b symbols instead of and respectively.

Edit: If you are using and signs, you only have to count them as a single byte each. This is to not give an unfair disadvantage.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Is a leading newline in the output acceptable? \$\endgroup\$
    – Steadybox
    Dec 3, 2017 at 20:52
  • 4
    \$\begingroup\$ I can't believe there is no Fugue answer yet! \$\endgroup\$
    – leo
    Dec 3, 2017 at 21:46
  • \$\begingroup\$ How strict is the output format? Can we ouput an an array of lines? How about a 2D-array with each element being a single note or character? \$\endgroup\$
    – Shaggy
    Dec 3, 2017 at 23:03
  • \$\begingroup\$ @Shaggy I don't know what the standard is for Kolmogorov complexity questions, so I'll say no. \$\endgroup\$
    – ericw31415
    Dec 4, 2017 at 1:02
  • 3
    \$\begingroup\$ : so much for monospace fonts in code elements \$\endgroup\$
    – chtenb
    Feb 26, 2018 at 13:21

11 Answers 11

8
\$\begingroup\$

Charcoal, 66 65 bytes (if using # and b)

↑⮌…0¦8‖O⸿×⁷♭M→×⁷♯→⸿⸿¹⁵FE⁸﹪⊕⊗ι⁷«⸿⸿✂׳FCGDAEBι⁺¹⁵ι→⸿✂⭆♭ ♯×⁷κι⁺¹⁵ι»⟲

Try it online! Link is to verbose version of code. Explanation:

↑⮌…0¦8‖O

Print the characters 0 to 7 reversed, then reflect with overlap. Lists normally print downwards, so printing upwards actually prints rightwards; we'll rotate everything into place at the end.

⸿×⁷♭M→×⁷♯

Start a new line and print 7 flats and 7 sharps with a gap in between.

→⸿⸿¹⁵

Leave a blank line and print 15 -s.

FE⁸﹪⊕⊗ι⁷«

Take the numbers 0 to 7, double them, add 1, then reduce modulo 7. Loop over the result.

⸿⸿✂׳FCGDAEBι⁺¹⁵ι

Leave a blank line and then take a 15-character slice of the triplicated string of notes starting at the current value.

→⸿✂⭆♭ ♯×⁷κι⁺¹⁵ι

On the next line take a 15-character slice of flats, spaces and sharps, each repeated 7 times.

»⟲

After printing all the notes, rotate everything into place.

\$\endgroup\$
2
  • \$\begingroup\$ You may count the and as 1 byte each rather than 3. \$\endgroup\$
    – ericw31415
    Dec 3, 2017 at 20:09
  • \$\begingroup\$ This is genius, I cannot compete with this solution. \$\endgroup\$
    – Charlie
    Dec 4, 2017 at 8:50
6
\$\begingroup\$

Ruby, 113 bytes (131 126 108 105 with # and b)

-7.upto(7){|i|print i.abs," ♭♯"[i<=>0]," - ",(4..11).map{|j|("FCGDAEB"*3)[k=j*2%7-i]+"♭♯ "[~k/7]}*" ",$/}

Try it online!

Ruby, 116 bytes (108 with # and b)

Try it online!

Ruby, 126 bytes (118 with # and b)

Try it online!

Ruby, 131 bytes with # and b

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ You need to print the Unicode sharp and flat characters because Ruby supports them. \$\endgroup\$
    – Jakob
    Dec 3, 2017 at 19:19
  • \$\begingroup\$ I think you should switch to the 124-byte solution. The metric here is bytes, not characters! \$\endgroup\$
    – Jakob
    Dec 3, 2017 at 19:49
  • \$\begingroup\$ You may count the and as 1 byte each rather than 3. \$\endgroup\$
    – ericw31415
    Dec 3, 2017 at 20:09
6
\$\begingroup\$

Python 3, 135 bytes

counting ♯ and ♭ as 1 byte each

thanks to Zacharý for -6 bytes.

for i in range(15):k=' ♯♭'[(i<7)-(i>7)]+' -';print(str(i-7)[-1]+k,*[v+k[a+8>i>a]for a,v in zip([1,3,5,0,2,4,6,1],('CDEFGAB'*8)[i*3:])])

Try it online!

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

GNU sed, 148 144 + 1 = 145 bytes

+1 byte for -r flag.

s/^/ 7# - C# D# E# F# G# A# B# \n65432101234567/
:
s/((.).(. - )((\S..){3})([^-]+)..\n)([0-7])/\1\2\7\3\6\2 \4\n/
s/ 0#/b0b/
t
s/^.//gm
s/0b/0 /

Try it online!

Explanation

First, insert a template of sorts:

 7# - C# D# E# F# G# A# B# 
65432101234567

Note the leading and trailing space on the first line.

In a loop, take the first number from the last line and replace it with parts of the second-to-last line like so:

 7# - C# D# E# F# G# A# B# 
│ └┬─┘└───┬───┘└───┬────┘
2  3      4        6
│  │      └────────│──┐
├──│────────────┐  │  │
│  │      ┌─────│──┘  │
│ ┌┴─┐┌───┴────┐│ ┌───┴───┐
 6# - F# G# A# B  C# D# E# 

As you can see, the initial space (capture 2) is used to replace the character after the B.

When the 0 is reached, replace the initial space with b. The loop continues, but instead of replacing #s with spaces, on each subsequent line a space is replaced with a b.

Finally, do a little cleanup: Remove the leading character from each line and replace 0b with 0.

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

Befunge, 134 132 130 bytes

<v:,,," - ",g2+!!\`0::,+*86*-1*2`0::p00:<75
@>4*65*+81v>55+,$$\:00g0`!\9p3+7%\1-:8+#^_
 b#"A"%7:\_^#:-1,*84,g2*+1`0g00!!g9%7:\+1,+

Try it online!

Explanation

  • We begin with an outer loop counting down from 7 to -7. We'll call this the row number.
  • For each row, we start by writing out '0'+abs(row) (the scale number), and then calculate (row>0)+(row!=0) to lookup whether it's natural, sharp, or flat in the table #b (you'll see this at the start of the third line of code).
  • We then calculate the scale's start note, n, as 30 + row*4. This will ultimately be mod 7, so think of it as the repeating sequence 2,5,1,4,0,3,6 (i.e. CFBEADG).
  • Our inner loop, i, then counts down from 8 to 1, for the eight notes in the scale, incrementing n on each iteration.
  • The letter of the note is simply 'A' + n%7. Whether it is sharp or flat is determined by looking up i%7 in a table. The table is initially all true, since the first scale is all sharps.
  • After each row is output, though, we update the table by toggling one value. On the first iteration we'll toggle the value at offset 5, but each loop the offset is adjusted by (offset+3)%7.
  • On the first half of the output, when the row is greater than zero, we're toggling these table values to false. On the second half of the output, when the row is less than or equal to zero, we're setting them back to true.
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Only can you actually golf in Befunge. \$\endgroup\$
    – Adalynn
    Dec 3, 2017 at 21:49
3
\$\begingroup\$

Bubblegum, 107 bytes

Bubblegum threshold

00000000: 4dca a90d 0301 1443 41ee 2a9e f4b1 a5ec  M......CA.*.....
00000010: 8d73 f7e1 fe8b 48a0 e968 aec1 3c87 d7f0  .s....H..h..<...
00000020: 1e3e c377 b80f 8ff9 a3ce c165 74d4 31b8  .>.w.......et.1.
00000030: 8c8a da07 1751 4fdb e022 ea69 1d5c 443d  .....QO..".i.\D=
00000040: 2d83 8ba8 a71b b888 7a5a 828b 524f 6b70  -.......zZ..ROkp
00000050: 51fa 690b 2e4b 47ed c165 e9a8 23b8 2c1d  Q.i..KG..e..#.,.
00000060: 7506 97a5 a3ae e0b2 74d4 0f              u.......t..

Try it online!

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

JavaScript (ES6), 130 124 bytes

Or 128 121 bytes with a leading newline.

f=(y=14,x=8)=>x?f(y,x-1)+' '+'BCDEFGA'[(y*3+x)%7]+'# b'[(x*5%7+y)/7|0]:(y?f(y-1)+`
`:'')+`${y<7?7-y+'#':y>7?y-7+'b':'0 '} -`

O.innerText = f()
<pre id=O style="font-size:11px"></pre>

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

C,  212   189   186  185 bytes

Thanks to @Jonathan Frech for saving a byte!

#define N n>0?35:98:32);
f(i,n){for(n=8;--n+8;puts(""))for(i=-1,printf("%d%c -",abs(n),n?N++i<8;)printf(" %c%c",(n*4+65+i)%7+65,"\377\277\273\233\231\211\10\0@Ddfv\367\377"[n+7]&1<<i?N}

Try it online!

Unrolled:

#define N n>0 ? 35 : 98 : 32);
f(i, n)
{
    for (n=8; --n+8; puts(""))
        for (i=-1, printf("%d%c -", abs(n), n?N ++i<8;)
            printf(" %c%c",
                (n*4+65+i)%7 + 65,
                "\377\277\273\233\231\211\10\0@Ddfv\367\377"[n+7] & 1<<i ? N
}
\$\endgroup\$
3
  • \$\begingroup\$ >- can be +. \$\endgroup\$ Feb 26, 2018 at 21:52
  • \$\begingroup\$ @JonathanFrech Thanks! \$\endgroup\$
    – Steadybox
    Feb 26, 2018 at 21:54
  • \$\begingroup\$ Suggest i=~!printf instead of i=-1,printf and \b instead of \10 \$\endgroup\$
    – ceilingcat
    Nov 7, 2019 at 3:42
2
\$\begingroup\$

Jelly,  57 56 55  54 bytes

-1 byte thanks to EriktheOutgolfer (use 7ŒR to replace -7r7)

_Ṃị“ b#”
=”B+\Çż
×3⁵+€ịØAḣ7¤ḊḊÇ€Z
7ŒRµṠÑżAW€żÇj€”-UK€Y

A full program printing the desired output (using #, b).

Try it online!

How?

_Ṃị“ b#” - Link 1, getSharpsFlatsOrSpaces: list of integers
 Ṃ       - minimum (of the input list)
_        - subtract (from the input list) -- for our purposes this resets whatever our
         -       1st value is to 0, since our inputs are always monotonically increasing
   “ b#” - literal list of characters = [' ', 'b', '#']
  ị      - index into (1-based and modular)

=”B+\Çż - Link 2, addSharpsFlatsOrSpaces: list of characters  e.g."CFBEADGCFBEADGC"
 ”B     - literal character 'B'
=       - equals? (vectorises)                      [0,0,1,0,0,0,0,0,0,1,0,0,0,0,0]
    \   - cumulative reduce with:
   +    -   addition                                [0,0,1,1,1,1,1,1,1,2,2,2,2,2,2]
     Ç  - call the last link (1) as a monad                       "##       bbbbbb"
      ż - zip (with input) ["#C","#F"," B"," E",...," F","bB","bE","bA","bD","bG","bC"]

×3⁵+€ịØAḣ7¤ḊḊÇ€Z - link 3, getNoteLetters: list of integers          e.g. [-7,-6,...,6,7]
×3               - multiply by three       [-21,-18,-15,-12,-9,-6,-3,0,3,6,9,12,15,18,21]
  ⁵              - literal ten                                                         10
   +€            - add for €ach (in [1,10])   [[-20,...,22],[-19,...,23],...,[-11,...31]]
          ¤      - nilad followed by link(s) as a nilad:
      ØA         -   yield uppercase alphabet                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        ḣ7       -   head to index seven                                        "ABCDEFG"
     ị           - index into ["ADGCFBEADGCFBEA","BEADGCFBEADGCFB","CFBEADGCFBEADGC",...]
           Ḋ     - dequeue    ["BEADGCFBEADGCFB","CFBEADGCFBEADGC","DGCFBEADGCFBEAD",...]
            Ḋ    - dequeue    ["CFBEADGCFBEADGC","DGCFBEADGCFBEAD","EADGCFBEADGCFBE",...]
             Ç€  - call the last link(2) as a monad for €ach
                 -    [[["#C","#F"," B"," E",...," F","bB","bE","bA","bD","bG","bC"],...]
               Z - transpose           [["#C","#D",...,"#C"],["#F",..." B",...,"#F"],...]

7ŒRµṠÑżAW€żÇj€”-UK€Y - Main link: no arguments
7ŒR                  - absolute range of seven     [-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7]
   µ                 - start a new monadic chain (call that r)
    Ṡ                - sign (of r)                 [-1,-1,-1,-1,-1,-1,-1,0,1,1,1,1,1,1,1]
     Ñ               - call the next link (1) as a monad                "####### bbbbbbb"
       A             - absolute value (of r)              [7,6,5,4,3,2,1,0,1,2,3,4,5,6,7]
      ż              - zip                      [[7,'#'],[6,'#'],...,[0,' '],...,[7,'b']]
        W€           - wrap €ach        [[[7,'#']],[[6,'#']],...,[[0,' ']],...,[[7,'b']]]
           Ç         - call the last link (3) as a monad (with r)      see link 3 example
          ż          - zip                     [[[['#',7]],["#C","#D",...,"#C"]],
                                                [[['#',6]],["#F",...," B",..."#F"]], ...]
              ”-     - literal character '-'
            j€       - join for €ach            [[['#',7],'-',"#C","#D",..."#C"],
                                                 [['#',6],'-',"#F",...," B",..."#F"],...]
                U    - upend (reverse each)     [[[7,'#'],'-',"C#","D#",..."C#"],
                                                 [[6,'#'],'-',"F#",...,"B ",..."F#"],...]
                 K€  - join €ach with spaces            [[7+"# - C# D# ... C#"],
                                                         [6+"# - F# ... B  ... F#"], ...]
                   Y - join with newlines
                     - implicit print to STDOUT
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I did have faith in Jelly for this one. \$\endgroup\$ Dec 4, 2017 at 21:15
0
\$\begingroup\$

CJam, 109 106 94 bytes

{_0={_z/}|" b#"=a}:A;15,{X7-_zs\A+" - "+o7,0+{YX+7%65+c"2461357"Y=aiX\-_7,#){;0}&AS++o}fYNo}fX

Try it online

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

Java 8, 255 bytes

Counting ♯ and ♭ as 1 byte each.

v->{String r="",t="GABCDEF";for(int i=-8;++i<8;r+="\n"){r+=(i<0?-i+"♯":i>0?i+"♭":"0 ")+" - ";for(String c:((t=t.substring(3)+t.substring(0,3))+t.charAt(0)).split(""))r+=c+("BEADGCF".substring(i<0?7+i:i).contains(c)?i<0?"♯":" ":i>0?"♭":" ")+" ";}return r;}

Explanation:

Try it online.

v->{                   // Method with empty unused parameter and String return-type
  String r="",         //  Result-String, starting empty
         t="GABCDEF";  //  Temp-String `t`, starting at "GABCDEF"
  for(int i=-8;++i<8;  //  Loop from -7 to 7 (inclusive); range (-8;8) == [-7;7]
      r+="\n"){        //    After every iteration: append the result with a new-line
    r+=                //   Append the result-String with:
       (i<0?           //    If `i` is negative:
         -i+"♯"        //     Append the absolute value of `i` + a literal "♯"
        :i>0?          //    Else-if `i` is positive:
         i+"♭"         //     Append `i` + a literal "♭"
        :              //    Else (`i` is 0):
         "0 ")         //     Append a literal "0" + space
     +" - ";           //   And then append a literal " - "
  for(String c:((t=t.substring(3)+t.substring(0,3))
                       //  Split String `t` in the middle,
                       //  and swap the two parts (i.e. "GABCDEF" becomes "CDEFGAB")
                +t.charAt(0))
                       //  Then append the first character
                .split(""))
                       //  And loop over each character:
     r+=c+             //   Append the result-String with this character, plus:
          ("BEADGCF".substring(i<0?
                       //    If `i` is negative
            7+i        //     Take the last `-i` characters of "BEAFGCF"
           :           //    Else (`i` is 0 or positive)
            i)         //     Take the last `7-i` characters of "BEAFGCF"
          .contains(c)?//    And if these last characters contain the current character:
            i<0?       //     And `i` is negative:
             "♯"       //      Append a literal "♯"
            :          //     Else (`i` is 0 or positive)
             " "       //      Append a space
          :i>0?        //    Else-if `i` is positive
            "♭"        //     Append a literal "♭"
          :            //    Else:
           " ")        //     Append a space
      +" ";}           //   And then append a space
  return r;}           //  Return the result-String
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.