Print me a scale

20

2

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.

ericw31415

Posted 2017-12-03T16:47:08.677

Reputation: 2 229

1Is a leading newline in the output acceptable? – Steadybox – 2017-12-03T20:52:21.540

4

I can't believe there is no Fugue answer yet!

– leo – 2017-12-03T21:46:26.040

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 – 2017-12-03T23:03:39.600

@Shaggy I don't know what the standard is for Kolmogorov complexity questions, so I'll say no. – ericw31415 – 2017-12-04T01:02:10.460

3: so much for monospace fonts in code elements – Chiel ten Brinke – 2018-02-26T13:21:57.663

Answers

8

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.

Neil

Posted 2017-12-03T16:47:08.677

Reputation: 95 035

You may count the and as 1 byte each rather than 3. – ericw31415 – 2017-12-03T20:09:37.130

This is genius, I cannot compete with this solution. – Charlie – 2017-12-04T08:50:07.703

6

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!

ovs

Posted 2017-12-03T16:47:08.677

Reputation: 21 408

6

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!

Level River St

Posted 2017-12-03T16:47:08.677

Reputation: 22 049

You need to print the Unicode sharp and flat characters because Ruby supports them. – Jakob – 2017-12-03T19:19:28.430

I think you should switch to the 124-byte solution. The metric here is bytes, not characters! – Jakob – 2017-12-03T19:49:49.987

You may count the and as 1 byte each rather than 3. – ericw31415 – 2017-12-03T20:09:57.060

5

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.

Jordan

Posted 2017-12-03T16:47:08.677

Reputation: 5 001

4

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.

James Holderness

Posted 2017-12-03T16:47:08.677

Reputation: 8 298

1Only can you actually golf in Befunge. – Zacharý – 2017-12-03T21:49:34.700

3

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!

ovs

Posted 2017-12-03T16:47:08.677

Reputation: 21 408

3

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
}

Steadybox

Posted 2017-12-03T16:47:08.677

Reputation: 15 798

>- can be +. – Jonathan Frech – 2018-02-26T21:52:00.467

@JonathanFrech Thanks! – Steadybox – 2018-02-26T21:54:23.473

Suggest i=~!printf instead of i=-1,printf and \b instead of \10 – ceilingcat – 2019-11-07T03:42:32.843

3

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>

Arnauld

Posted 2017-12-03T16:47:08.677

Reputation: 111 334

2

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

Jonathan Allan

Posted 2017-12-03T16:47:08.677

Reputation: 67 804

1I did have faith in Jelly for this one. – Erik the Outgolfer – 2017-12-04T21:15:00.620

0

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

Chiel ten Brinke

Posted 2017-12-03T16:47:08.677

Reputation: 201

0

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

Kevin Cruijssen

Posted 2017-12-03T16:47:08.677

Reputation: 67 575