Print me a scale

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.

• Is a leading newline in the output acceptable? – Steadybox Dec 3 '17 at 20:52
• I can't believe there is no Fugue answer yet! – leo Dec 3 '17 at 21:46
• 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? – Shaggy Dec 3 '17 at 23:03
• @Shaggy I don't know what the standard is for Kolmogorov complexity questions, so I'll say no. – ericw31415 Dec 4 '17 at 1:02
• ♭: so much for monospace fonts in code elements – Chiel ten Brinke Feb 26 '18 at 13:21

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

↑⮌…0¦8‖Ｏ⸿×⁷♭Ｍ→×⁷♯→⸿⸿¹⁵ＦＥ⁸﹪⊕⊗ι⁷«⸿⸿✂×³FCGDAEBι⁺¹⁵ι→⸿✂⭆♭ ♯×⁷κι⁺¹⁵ι»⟲


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

↑⮌…0¦8‖Ｏ


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.

⸿×⁷♭Ｍ→×⁷♯


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

→⸿⸿¹⁵


Leave a blank line and print 15 -s.

ＦＥ⁸﹪⊕⊗ι⁷«


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.

• You may count the ♯ and ♭ as 1 byte each rather than 3. – ericw31415 Dec 3 '17 at 20:09
• This is genius, I cannot compete with this solution. – Charlie Dec 4 '17 at 8:50

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! • You need to print the Unicode sharp and flat characters because Ruby supports them. – Jakob Dec 3 '17 at 19:19 • I think you should switch to the 124-byte solution. The metric here is bytes, not characters! – Jakob Dec 3 '17 at 19:49 • You may count the ♯ and ♭ as 1 byte each rather than 3. – ericw31415 Dec 3 '17 at 20:09 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! 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. Befunge, 134132 130 bytes <v:,,," - ",g2+!!\0::,+*86*-1*20::p00:<75 @>4*65*+81v>55+,$$\:00g0!\9p3+7%\1-:8+#^_ b#"A"%7:\_^#:-1,*84,g2*+10g00!!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. • Only can you actually golf in Befunge. – Zacharý Dec 3 '17 at 21:49 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! 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>

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
}

• >- can be +. – Jonathan Frech Feb 26 '18 at 21:52
• @JonathanFrech Thanks! – Steadybox Feb 26 '18 at 21:54
• Suggest i=~!printf instead of i=-1,printf and \b instead of \10 – ceilingcat Nov 7 at 3:42

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     - literal character 'B'
=       - equals? (vectorises)                      [0,0,1,0,0,0,0,0,0,1,0,0,0,0,0]
\   - cumulative reduce with:
Ç  - 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]]
ØA         -   yield uppercase alphabet                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
ḣ7       -   head to index seven                                        "ABCDEFG"
-    [[["#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']]]
ż          - 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

• I did have faith in Jelly for this one. – Erik the Outgolfer Dec 4 '17 at 21:15

CJam, 109106 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

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:
//    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