[Question]
  [
Given two note names, you are to write a program that determines if the interval formed by these two notes is consonant or dissonant.
# Introduction
In Western music, there are only 12 "different" tones. Their names, sorted from lowest to highest, are these: `C, C#, D, D#, E, F, F#, G, G#, A, A#, B`. The sequence is cyclical, i. e. it continues with another `C` after the `B`, infinitely.
The distance between two tones is called an *interval*. The interval between any two notes that are adjacent in the series above (e. g. `C — C#` or `E — F`) is called a *semitone*. The interval between more distant notes is defined as the number of semitone steps needed to get from the first to the second (while possibly wrapping around the sequence). Some examples: `D to E` = 2 semitones, `C to G` = 7 semitones, `B to D#` = 4 semitones (this wraps around the sequence).1
Now, these intervals are divided into two categories: *consonant* (pleasantly sounding if you play the two notes at once) and *dissonant* (not so much).
Let's define the consonant intervals to be: 0, 3, 4, 5, 7, 8 and 9 semitones.
The rest of them is dissonant, namely: 1, 2, 6, 10 and 11 semitones.
# The Challenge
Write a "program" (in the usual broad sense of the word: a function is perfectly OK) to do the following:
* Take two note names (strings from the sequence above) as an input. You may take them however you like (from stdin, as arguments, separated by whatever you want, even feel free to take them as a list of characters (e. g. `["C","#"]`). However, you may not assign any other names to the notes (especially you may not number them from 0 to 11 and use the numbers).
* For you music geeks out there, the notes will be specified without the octave. In this case, it also does not matter in which order the notes come and which is lower and which is higher. Finally, you don't need to handle any names not in the list above. No other enharmonics like `E#`, no flats, double-alterations and so on.
* Pick any two different values. Your program must output one of them whenever the interval formed by the two notes in the input is consonant, and the other if they are not. (Could be `True` and `False`, but even π and e if you want :))
* This is a code-golf. The shortest program in bytes in each language wins. Have fun!
# Examples and Test Cases
```
Note 1    Note 2    Output    Interval [semitones]
  C          D     Dissonant   2
  A#         A#    Consonant   0
  G          D     Consonant   7 (wraparound)
  D#         A     Dissonant   6
  F          E     Dissonant   11
  A          C     Consonant   3
```
I don't add more of them since there aren't any particularly treacherous cases in this. 
This is a first challenge of mine, so any constructive criticism is warmly welcome :—). If you find the theory explanation sloppy, feel free to ask questions. Finally, please do not tell me that this is a dupe of [this](https://codegolf.stackexchange.com/questions/76120/music-interval-solver) or [this](https://codegolf.stackexchange.com/questions/8523/the-major-minor-dichotomy). I made sure it's not. (The latter is quite similar but more complex. I thought that putting up a little simpler challenge will make it easier for people to join.)
---
1: I tried to simplify this explanation as far as I could. There's a lot more theory around intervals. Please don't bash me for leaving it out.
  
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 21 bytes
Takes input as a list of two strings. Returns `0` for dissonant or `1` for consonant.
```
OḢ6×%21_Lµ€IA“¬ɠṘ’æ»Ḃ
```
[Try it online!](https://tio.run/##ATsAxP9qZWxsef//T@G4ojbDlyUyMV9MwrXigqxJQeKAnMKsyaDhuZjigJnDpsK74biC////WyJBIiwiRCMiXQ "Jelly – Try It Online")
```
OḢ6×%21_Lµ€IA“¬ɠṘ’æ»Ḃ   - main link
         µ€             - for each note             e.g. ["A#", "C"]
O                       -   convert to ASCII codes  -->  [[65, 35], 67]
 Ḣ                      -   keep the first element  -->  [65, 67]
  6×                    -   multiply by 6           -->  [390, 402]
    %21                 -   modulo 21               -->  [12, 3]
       _L               -   subtract the length     -->  [12, 3] - [2, 1] = [10, 2]
           IA           - absolute difference       -->  8
             “¬ɠṘ’      - the integer 540205
                  æ»    - right-shift               -->  540205 >> 8 = 2110
                    Ḃ   - isolate the LSB           -->  2110 & 1 = 0
```
### Making-of
We first should note that the function **F** that we're looking for is commutative: for any pair of notes **(A, B)**, we have **F(A, B) = F(B, A)**.
Since there are not too many possible inputs and only 2 possible outputs to deal with, it must be possible to find a rather simple hash function **H**, such that **|H(A) - H(B)|** produces a limited range of values and is collision-free for all possible pairs of notes **(A, B)** with respect to the expected output.
We're going to test the set of functions **H(mul, mod)**, which are defined as:
```
H(mul, mod)(s) = ((ORD(s[0]) * mul) MOD mod) - LEN(s)
```
Where `ORD(s[0])` is the ASCII code of the first character of the note and `LEN(s)` is the length of the note (**2** if there's a `'#'` and **1** if not).
Below is a commented version of the JS code that was used to find a couple of valid pairs ***(mul, mod)*** and the resulting bitmasks. There are many possible solutions, but `* 6 % 21` is the shortest one with this method.
```
// all 12 notes
note = ['C','C#','D','D#','E','F','F#','G','G#','A','A#','B'];
// reference implementation that takes 2 notes
// and returns 0 for dissonant or 1 for consonant
F = (a, b) =>
  +!~[1, 2, 6, 10, 11].indexOf((note.indexOf(a) - note.indexOf(b) + 12) % 12)
for(mul = 1; mul < 100; mul++) {
  for(mod = 1; mod < 31; mod++) {
    // hash function
    H = s => s.charCodeAt() * mul % mod - s.length;
    table = {};
    // for all possible pairs of notes (a, b)
    if(note.every(a => note.every(b => {
      // compute the table index
      idx = Math.abs(H(a) - H(b));
      // and the expected result
      res = F(a, b);
      // if the slot is empty, store the correct value
      if(table[idx] === undefined) {
        table[idx] = res;
        return 1;
      }
      // else, make sure that the correct value is already there
      return table[idx] == res;
    }))) {
      // if all tests pass: translate the table into a binary mask
      for(n = 0, msk = 0; n < 31; n++) {
        msk |= (table[n] || 0) << n;
      }
      // and display the result
      console.log('mul ' + mul + ', mod ' + mod + ' --> ' + msk);
    }
  }
}
```
[Answer]
# [APL (Dyalog)](https://www.dyalog.com/), ~~62~~ 39 bytes
Uses `⎕IO←0`; 0 is consonant, 1 is dissonant. Takes list of base note chars as left argument and list of sharps as right argument.
```
{⎕A[|-/('C D EF G A '⍳⍺)+⍵=⍕#]∊'BCGKL'}
```
[Try it online!](https://tio.run/##SyzI0U2pTMzJT///qG@qp/@jtgkG/9OAZDWQ6xhdo6uvoe6s4KLg6qbgruCooP6od/Oj3l2a2o96t9o@6p2qHPuoo0vdydnd20e99v9/dWcXdYU0BXUFBXUudUdHMFtZGch2RxJ3gYqD2G6uSOqdYWwA "APL (Dyalog Unicode) – Try It Online")
`{`…`}` anonymous function where `⍺` is the left argument and `⍵` is the right argument
 `⎕A[`…`]∊'BCGKL'` is the **A**lphabet, indexed by the following, a member of the string?
  `⍕#` format the root namespace (yields the sharp character)
  `⍵=` are the right argument chars (the sharps) equal to that?
  `(`…`)+` add the following:
   `'C D EF G A '⍳⍺` indices of the left argument chars in the string 
  `-/` difference between those
  `|` absolute value
[Answer]
# [MATL](https://github.com/lmendo/MATL), ~~30~~ ~~27~~ 26 bytes
```
,j'DJEFPGIALBC'&mQs]ZP7Mdm
```
Inputs the two notes in different lines. Outputs `0` for consonant, `1` for dissonant.
[Try it online!](https://tio.run/##y00syfn/XydL3cXL1S3A3dPRx8lZXS03sDg2KsDcNyX3/38XZS5HAA) Or [verify all test cases](https://tio.run/##y00syfmf8F8nS93Fy9UtwN3T0cfJWV0tN7A4NirA3Dcl979LyH9nLhcuR2UQcgeyXIAsLjcuVyDpDAA).
### Explanation
The 11-character string
```
DJEFPGIALBC
```
encodes both the notes and the dissonant intervals, as follows.
The program first *finds the 1-based indices of the input characters* in the above string. A non-sharp input like `D` will give `1`, `E` will give `3`, ..., `C` will give `11`. These numbers can also be considered 1×1 numeric arrays. A sharp input like `C#` will give the 1×2 array `[11 0]`, meaning that `C` was found at position `11` and `#` was not found.
Observe that letters `JPIL` will never be present in the input. For now they are only used as placeholders, so that for example note `E` is *two* semitones above `D`. But they will also be useful to define dissonant intervals.
The numbers in the first entry of the 1×1 or 1×2 array correspond to note pitch in semitones, not counting sharp symbols (yet). Observe that the scale defined by these numbers doesn't start at `C`; but that doesn't matter because we only want intervals, that is, *differences* between notes. Subtracting the obtained numbers would give either the interval or 12 minus the interval. But first we need to consider the sharp symbol.
To consider sharp notes, a golfy way (in MATL) is to add `1` to each entry of the 1×1 or 1×2 array obtained previously and then sum the array (2 bytes). Thus non-sharp notes are increased by `1` and sharp notes by `2`. This makes sharp notes 1 semitone higher than non-sharp notes, as required. We are also adding an extra semitone to all notes, but that doesn't change the intervals between them. So now note `D` will give pitch number `2`, `D#` will give `3`, ..., `C` will give `12`, `C#` will give `13`.
Dissonant intervals are `1`, `2`, `6`, `10`, or `11`. These have a *modulo-12 symmetry*: an interval between two notes is dissonant if and only if the interval with the notes in reverse order, modulo 12, is dissonant.
If we compute the consecutive differences of the string `'DJEFPGIALBC'` we get the numeric vector
```
6 -5 1 10 -9 2 -8 11 -10 1
```
which contains precisely the dissonant intervals, in addition to some negative values, which will be neither useful nor harmful. Observe that it is the choice of additional letters `JPIL` in the string `'DJEFPGIALBC'` that defines (via consecutive differences) the dissonant intervals.
To see if the two input notes are dissonant we take the *absolute difference* of their pitch numbers. For example, `C` and `D#` will give numbers `12` and `3` respectively, and the absolute difference is `9`. The actual difference would be `-9`, and the actual interval would be `3` (obtained as `-9` modulo 12). But thanks to the symmetry referred to above, we can consider `9` instead of `3`. Since `9` is not present in the vector of consecutive differences, the notes are consonant.
[Answer]
# JavaScript (ES6), ~~68~~ 64 bytes
Takes the notes as two strings in currying syntax `(a)(b)`. Returns `0` for dissonant or `1` for consonant.
```
a=>b=>488055>>(g=s=>'C D EF G A'.search(s[0])-!s[1])(a)-g(b)+9&1
```
### Test cases
```
let f =
a=>b=>488055>>(g=s=>'C D EF G A'.search(s[0])-!s[1])(a)-g(b)+9&1
console.log(f('C' )('D' )) // 0 (Dissonant)
console.log(f('A#')('A#')) // 1 (Consonant)
console.log(f('G' )('D' )) // 1 (Consonant)
console.log(f('D#')('A' )) // 0 (Dissonant)
console.log(f('F' )('E' )) // 0 (Dissonant)
console.log(f('A' )('C' )) // 1 (Consonant)
```
### Formatted and commented
```
a => b =>                       // given the two notes 'a' and 'b'
  488055 >>                     // 19-bit lookup bitmask: 1110111001001110111
    (g = s =>                   // we use g() to convert a note 's' into a semitone index
      'C D EF G A'.search(s[0]) // position of the note: -1 for 'B' (not found) to 9 for 'A'
      - !s[1]                   // subtract 1 semitone if the '#' is not there
    )(a)                        // compute the result for 'a'  --> [ -2 ...  9]
    - g(b)                      // subtract the result for 'b' --> [-11 ... 11]
    + 9                         // add 9                       --> [ -2 ... 20]
  & 1                           // test the bitmask at this position (0 if negative or > 18)
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 26 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
i@€ØAo.SḤ’d5ḅ4µ€ạ/“¢£©½¿‘ċ
```
A monadic link taking a list of the two notes (as lists of characters) and returning `0` for consonant and `1` for dissonant.
**[Try it online!](https://tio.run/##AWQAm/9qZWxsef//aUDigqzDmEFvLlPhuKTigJlkNeG4hTTCteKCrOG6oS/igJzCosKjwqnCvcK/4oCYxIv//0MgQyMgRCBEIyBFIEYgRiMgRyBHIyBBIEEjIEL/WyJEIyIsICJHIyJd "Jelly – Try It Online")** or see all inputs in the [test-suite](https://tio.run/##y0rNyan8/z/T4VHTmsMzHPP1gh/uWPKoYWaK6cMdrSaHtgKFH@5aqP@oYc6hRYcWH1p5aO@h/Y8aZhzp/v9wx6ZDW49OOtJtHaoCZOw53A5UmwXEINQwR0Fb4VHD3CwoxwrEifzvrOCsrOCi4KKs4KrgpuCmrOCu4K6s4KjgqKzghFcSAA "Jelly – Try It Online").
### How?
```
i@€ØAo.SḤ’d5ḅ4µ€ạ/“¢£©½¿‘ċ - Link: list of lists of characters, notes
              µ€           - for €ach note in notes: (call the resulting list x)
   ØA                      -   yield the uppercase alphabet
i@€                        -   first index of c in ^ for €ach character, c
                           -     ...note '#' is not there so yields 0 (A->1, B->2,...)
      .                    -   literal one half
     o                     -   or (vectorised)  - e.g. "C#" -> [3, 0] -> [3, 0.5]
       S                   -   sum
        Ḥ                  -   double - that is ...  C C#  D D#  E  F F#  G G#  A A#  B
                                                 ->  6  7  8  9 10 12 13 14 15  2  3  4
         ’                 -   decrement         ->  5  6  7  8  9 11 12 13 14  1  2  3
           5               -   literal five
          d                -   divmod                (e.g. 9 -> [1,4] or 11 -> [2,1])
             4             -   literal four
            ḅ              -   convert from base     (e.g. [1,4] -> 8 or [2,1] -> 9)
                                                 ->  4  5  6  7  8  9 10 11 12  1  2  3
                 /         - reduce x with:
                ạ          -   absolute difference   (e.g. ["G#", "A"] -> [12, 1] -> 11)
                  “¢£©½¿‘  - code-page indices = [1, 2, 6, 10, 11]
                         ċ - count occurrences (1 if in the list, 0 if not)
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 31 bytes
```
O_65ị“¢[ḋṃ’b⁴¤+L$€Ḣ€ạ/e“cṾ’b12¤
```
[Try it online!](https://tio.run/##y0rNyan8/98/3sz04e7uRw1zDi2Kfrij@@HO5kcNM5MeNW45tETbR@VR05qHOxaByF0L9VOBqpIf7twHUmBodGjJ////lRyVdBSU3JWVAA "Jelly – Try It Online")
wheeeeee 32 bytes too long
# Explanation
```
O_65ị“¢[ḋṃ’b⁴¤+L$€Ḣ€ạ/e“cṾ’b12¤  Main link
O                                Cast each character to an int using Python `ord`
 _65                             Subtract 65 (A is 0, G is 7)
     “¢[ḋṃ’b⁴¤                   [2, 3, 5, 7, 9, 10, 0]
     “¢[ḋṃ’                      37058720
           b                     Digits in base
            ⁴                    16
    ị                            Index into this list; this creates the gaps for sharps
                 €               For each sublist
              +L$                Add the length to each element (Sharpens sharp notes)
              +                  Add
               L                 Length
                   €             For each sublist
                  Ḣ              Take the first element
                    ạ/           Absolute difference between the two (unoctaved) pitches # It's convenient that every interval's inverse (?) has the same consonance/dissonance
                      e          Is the semitone difference in
                       “cṾ’b12¤  [1, 2, 6, 10, 11]?
                       “cṾ’      25178
                           b     base
                            12   12
```
[Answer]
# Mathematica, 55 bytes
```
function                                                  arguments        bytes
FreeQ[1|2|6|10|11]@Abs[#-#2&@@Sound`PitchToNumber/@#]&    [{"C","F#"}]     55
```
Map the internal built-in `Sound`PitchToNumber` on the input (list of two strings), take the absolute difference, then pattern match for dissonant interval numbers.
---
## Just for fun (non-competing)
Here are some shorter functions that violate the restriction “you may not assign any other names to the notes.” The [rudimentary `Music`` package](http://reference.wolfram.com/language/Music/guide/MusicPackage.html) has predefined note constants (like `A4 = 440.`) and the function `HertzToCents` (which can be golfed). Instead of strings, we will use the note constants as arguments, but given in a different format for each function.
```
FreeQ[1|2|6|10|11]@Abs@@Round[.01HertzToCents@#]&         [{C3,Fsharp3}]   50+9=59
FreeQ[1|2|6|10|11]@Abs@Round[17Log[#2/#]]&                [C3,Fsharp3]     43+9=52
FreeQ[1|2|6|10|11]@Abs@Round[17Log@#]&                    [C3/Fsharp3]     39+9=48
```
The package import `<<Music`;` takes 9 bytes.
This function converts a string (like `"F#"`) into a note constant (like `Fsharp3`):
```
Symbol[StringReplace[#,"#"->"sharp"]<>"3"]&                                44
```
To accept intervals larger than an octave, replace `Abs[…]` with `Mod[…,12]`.
---
Why are some intervals considered dissonant? An interval is a ratio of two frequencies. If the ratio has a “simple” numerator and denominator, it tends to be more consonant. In [5-limit tuning](https://en.wikipedia.org/wiki/Five-limit_tuning), ratios can be factored into integer powers of only prime numbers less than or equal to 5. No interval in equal temperament, besides the octave, is a [just interval](https://en.wikipedia.org/wiki/Just_intonation); they are merely close approximations using powers of the 12th root of 2.
Instead of hard-coding which interval numbers are dissonant, we can find a rational approximation of the interval and then determine if its numerator and denominator are “simple” (meaning that the denominator is less than 5 and the ratio does not divide 7).
This table shows each of the steps in that process.
```
Table[
  Module[{compoundInterval,simpleInterval,rationalApprox,denomLeq5,div7,consonant},
    compoundInterval = Power[2, i/12];
    simpleInterval   = 2^Mod[Log2[compoundInterval], 1];
    rationalApprox   = Rationalize[N@simpleInterval, 1/17];
    denomLeq5        = Denominator[rationalApprox]<=5;
    div7             = Denominator[rationalApprox]>1 && rationalApprox\[Divides]7;
    consonant        = FreeQ[1|2|6|10|11][Mod[i,12]];
    InputForm/@{
      i, simpleInterval, rationalApprox, 
      denomLeq5, div7, denomLeq5 && !div7,
      consonant
    }
  ], {i, 0, 12}
]
i   sInterval  ratio   denomLeq5  div7       den&&!div  | consonant?
0   1          1       True       False      True       | True
1   2^(1/12)   17/16   False      False      False      | False
2   2^(1/6)    9/8     False      False      False      | False
3   2^(1/4)    6/5     True       False      True       | True
4   2^(1/3)    5/4     True       False      True       | True
5   2^(5/12)   4/3     True       False      True       | True
6   Sqrt[2]    7/5     True       True       False      | False
7   2^(7/12)   3/2     True       False      True       | True
8   2^(2/3)    8/5     True       False      True       | True
9   2^(3/4)    5/3     True       False      True       | True
10  2^(5/6)    7/4     True       True       False      | False
11  2^(11/12)  11/6    False      False      False      | False
12  1          1       True       False      True       | True
```
The rational approximation lies within `1/17` of the interval because that is the largest threshold that distinguishes between all 12 equal tempered intervals. We match rational numbers with the pattern `Rational[a_,b_]` (or just `a_~_~b_`) first, and then match integers with only `_`.
This culminates in the following rather short function that determines if an arbitrary frequency ratio (greater than 1) is consonant or dissonant.
```
Rationalize[#,1/17]/.{a_~_~b_:>b<=5&&!a∣7,_->True}&       [Fsharp3/C3]     51+9=60
```
[Answer]
# Mathematica, 118 bytes
```
FreeQ[{1,2,6,10,11},Min@Mod[Differences[Min@Position["C|C#|D|D#|E|F|F#|G|G#|A|A#|B"~StringSplit~"|",#]&/@{#,#2}],12]]&
```
  
**Input form**
> 
> ["A#","D"]
> 
> 
> 
**Outputs** 
```
True->Consonant  
False->Dissonant   
```
thanks @JonathanFrech -16 bytes
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 30 bytes
```
≔B#A#G#FE#D#Cζ§”o∧⌈ς”⁻⌕ζ⮌θ⌕ζ⮌η
```
[Try it online!](https://tio.run/##S85ILErOT8z5/9@xuDgzPU9DyUnZUdld2c1V2UXZWUlHoUrTmiugKDOvRMOxxDMvJbVCQ8nQwMDQ0BCMDZQUfDPzSos13DLzUjSqdBSCUstSi4pTNQo1NXUU0AUzNEHA@v9/F2Uux/@6Zf91i3MA "Charcoal – Try It Online") Link is to verbose version of code. Outputs 1 for consonant, 0 for dissonant. Explanation:
```
≔B#A#G#FE#D#Cζ                  Store reversed note names in z
                        θ       First input
                       ⮌        Reversed
                     ⌕ζ         Find index in z
                            η   Second input
                           ⮌    Reversed
                         ⌕ζ     Find index in z
                     ⁻          Subtract
               ”o∧⌈ς”           Compressed string 100111011100
              §                 Circularly index
                                Implicitly print
```
[Answer]
# J, 68 bytes
```
[:e.&1 2 6 10 11[:(12| -~/)(<;._1',C,C#,D,D#,E,F,F#,G,G#,A,A#,B')i.]
```
## explanation
A straightforward, not super golfed implementation in J:
* Input is given as boxed itemized notes (produced using cut), in order.
* Find their indexes in the range of notes: `(<;._1',C,C#,D,D#,E,F,F#,G,G#,A,A#,B')i.]`
* Subtract the first from the second: `-~/`
* Take the remainder when divided by 12: `12|`
* Check if it's one of the dissonant notes: `e.&1 2 6 10 11`
[Try it online!](https://tio.run/##bY9Na8JAEIbv@ysGFpoEpttMhAi2HtbdJLf@AREJftD0sBGj9FL61@PqaNQme1jm45n3nflu2@1UwXyyUS8ECaRAMRDNJyElv/D69xaFH@9qSQEaNBItWokZ5phLLLCQqFFLnAVRpRbic6aAoGpgXTVN7Up3QIjP@ap2nAtRud3xAN7xoio2q6/az0xhC9w5@9iA6/FT3ftoOdgpuolnJb@qHmzkmA1boAnE5Qww0D3L/@0mHyfMaNkxHJrbnT6OmSn@6zwyYwh/9uWu3NdHt454wD6I9oxTZvK7aNZjiK7b3SHTcx617Qk "J – Try It Online")
[Answer]
# [///](https://esolangs.org/wiki////), ~~90~~ 88 bytes
```
/^/"\///^\/\///C^D/##"E/DD"F/E#"G/FD"A/GD"B/AD"#,#/,"B#^B/#"A#/#"A^G#^G^F#/#"F^E^D#^D/#/
```
[Try it online!](https://tio.run/##ZczBCsIwDIDhu09RkovCIE5Bz@3S9iVGoDhBQTZZFR@/Nh6GsB7awNf8@ZHy7ZpLISHoiUh60qcTJkTwxAyBPEKkwGApMjiyDNggNeBQHCFY1EsiSpSgcxAvjJqgjTGmaxyy0TPcc57GNL7qfKhksZJFpcs0LrTXrbhs/dPZbD9zeqZ5eo/Drv7jX2JVP2kiVPIrals1W61b5Y@lfAE "/// – Try It Online") (all test cases at once)
* Put the input after the code.
* Separate the note names with `,B#` in each test case.
* The output is `,` for consonant, `,#` for dissonant.
* Support for double-alterations (`##`) or `E#` in some particular cases. Otherwise the output is `,` for consonant, `#,` for dissonant (thanks to modulo 12 symmetry)
* Can handle multiple test cases at once (if separated reasonably)
* Lowercase characters are printed exactly.
[Answer]
# [C (gcc)](https://gcc.gnu.org/), 91 bytes
```
g(char*s){return (s[1]&1|2**s&15)*4/5;}f(char*x,char*y){return (1952220<<g(x)>>g(y))&2048;}
```
call: `f("A#", "D")`
Return value:
* Consonant: 2048
* Dissonant: 0
Bonus: The function is case insensitive.
[Try it online!](https://tio.run/##ZY/basMwDIbv/RQipcF20y02DWxzFtipe4i2F8U5NLA5I06hJcuzZ468MbbefJLMh35ZLyutx7Gi@rBvuWV9W3TH1gC1G7ELxafk3IYiYXx1naih9NopwnL@tcVtIqWM07SiJ5ZlFT0zFsp4daOGcVYb/XbMC0htl9fN1SEjpDYdvO9rQxnpCQCuA9N0hd3s4B56CB6CyGE28XHCEwLnZwS2LxPWCJxfEVMbw6CIW102LfirfYBw6zFIAcdZwWKBDXP2pS//@fLHl94H@Gjdb0oazKWFJTjewTzfGneDD/iuMoKS/n1hTJGBjF8 "C (gcc) – Try It Online")
[Answer]
# Python 2, ~~125 117 83 78~~ 77 bytes
```
a,b=map("C C#D D#E F F#G G#A A#B".index,input())
print chr(abs(a-b))in""
```
Where the `""` at the end actually contains the characters `"\x02\x04\x0c\x14\x16"`
[Try it Online!](https://tio.run/##LYzBCsIwEERBPBWP4nmZXBKogh6VHtqk7T/0ltZAAxpDrVi/vm7Fy77ZmZ2Nn7F/hNPcZAOA2aZtdrdRQpMWhowoqaJK1FSLnHJR4ODD1U2pD/E1SqWSOPgwUtcP0rZPafetUj5gtd5sd5j548VNrsO79zdHx/OyUMOBRgqDBLlgwSNB/XfMz2FRMcvlhKmZS6XAFw)
(+3 because I forgot 11 or 22 in the list to begin with)
-8 bytes from Jonathan Frech and switching to Python *2*.
-34 bytes with suggestions from Jonathan Frech and using `str`'s index instead of `list`'s.
-4 bytes from inlining `i` and Neil's reversing the string suggestion (only -2 really, as i forgot `()` around a generator)
-5 bytes from un-inlining `i` & changing the input format
-1 bytes from Jonathan Frech with `map()` and unprintables.
Takes input in one line of stdin in the format:
```
'C','C#'
```
`True` is dissonant, `False` is consonant.
Old Explanation:
```
i='C C#D D#E F F#G G#A A#B'.index
a,b=input()
print abs(i(a)-i(b))in[2,4,12,20]
```
Python `str.index` returns the lowest (positive) starting index of a matching substring, so
`"ABACABA".index("A") == 0` and `"ABACABA".index("BA") == 1`. Because of this, we can put the note names evenly spaced in a string, and as long as (for example) `A` comes before `A#`, the shared `A` won't be a problem.
```
i='C C#D D#E F F#G G#A A#B'.index
```
`i` is now a function that returns the index in `'C C#D D#E F F#G G#A A#B'` its argument (a note name) is, which is 2 \* (the number of semitones that note is up from `C`)
```
a,b=input()
```
Python 2's `input()` is (mostly) equivalent to `eval(input())` in Python3, so with a valid input of the format `'C#','F'` (for example), `a='C#'` and `b='F'`
```
print abs(i(a)-i(b))in[2,4,12,20]
```
If the disttance between the first note and the second note in the string is not 2, 4, 12, or 20 (since the note names are represented in 2 characters), then the interval is dissonant, print True, else it is consonant, print False.
[Answer]
# [C (gcc)](https://gcc.gnu.org/), 115 ~~117~~ ~~120~~ bytes
```
g(char*a){a=*a-65+!!a[1]*(7-*a/70-*a/67);}f(x,y)char*x,*y;{x="(pP$HL<lt<X"[g(x)]*32+"=ZukW-^h1F
6"[g(x)]>>g(y)&1;}
```
[Try it online!](https://tio.run/##S9ZNT07@/z9dIzkjsUgrUbM60VYrUdfMVFtRMTHaMFZLw1xXK1Hf3ABEmplrWtemaVToVGqCVVfoaFVaV1fYKmkUBKh4@IjY5JTYRChFp2tUaMZqGRtpK9lGlWaH68ZlGLpxm0HF7ezSNSo11Qyta//nJmbmaWhyVXMVFGXmlaRpKKmmxOQp6QAZ7spKOkrOSpqa1jjkXPDIuYLlav8DAA "C (gcc) – Try It Online")
Return 1/0 for consonat and dissonat. It is always interesting to do string manipulation with pure C. Take input as `f("A#", "C")`
[Answer]
# [PowerShell](https://github.com/TryItOnline/TioSetup/wiki/Powershell), 107 bytes
```
param($a,$b)[math]::abs(($x=-split'C C# D D# E F F# G G# A A# B').indexof($b)-$x.indexof($a))-in1,2,6,10,11
```
[Try it online!](https://tio.run/##RcyxCsMgEADQXzlQOAUttUOHQIc0ifmI0uFCLRFMIjFQ//7areNbXt4@YS9zSIk5006LkmTkpB8LHfOzaWgqSsl6syWneGAHnYAeegEDePACRhgFtNAKuKM@xfUV6vZWv8DK@idpbePqzMVcjTsb55gZPTIO@AU "PowerShell – Try It Online")
Outputs `True` for dissonant and `False` for consonant.
Takes input `$a` and `$b`, the two notes, as strings. Performs a `-split` operation on the scale, which splits on whitespace, to create an array of the notes, stores that into `$x`. Finds the `.indexof` `$b` in that array, subtracts the index of `$a`, and then takes the `abs`olute value thereof. Checks whether that number is `-in` the dissonant ranges.
[Answer]
# [Python 2](https://docs.python.org/2/), 68 bytes
```
lambda a,b,f='C C#D D#E F F#G G#A A#B'.find:3142>>(f(a)-f(b))/2%12&1
```
[Try it online!](https://tio.run/##XcrRCoIwFMbx@57iwKhtYcWsixAU5qY@hHUxsdWgpohd9PSWeuGhm8Pv/PnaT/9ofDjY@DI8zauqDZigCmxMFSiiQZMMcshJAQWRIElK99b5OjqKU5gkzDLDd5ZVnB/CtQg3YrBNBw6ch874@42JM4@g7ZzvwbKt8@27Z5wPJVU0AKrpdVVSSUb/7vgUS9dzn5yPzOb5SDVR/ZMs1ogoZwtzRLQoEFGWiCin9PoF "Python 2 – Try It Online")
Outputs: `1` is dissonant, `0` is consonant.
[Answer]
# SQL, 582 bytes
[SQL Fiddle](http://sqlfiddle.com/#!6/e683f/1/0)
I still have some golfing to do on it, but I wanted to get it down here before I end up breaking it completely.
If the input is in a letter format, then putting those letters in a table with values is okay, right?
```
CREATE TABLE N(N char(2),v int)
Insert Into N values('A',1),('A#',2),('B',3),('C',4),('C#',5),('D',6),('D#',7),('E',8),('F',9),('F#',10),('G',11),('G#',12);
CREATE TABLE D(D char(9),v int) 
Insert Into D values('C',0),('D',1),('D',2),('C',3),('C',4),('C',5),('D',6);
CREATE FUNCTION I(@A char(2),@B char(2))
RETURNS char(9) as
BEGIN
DECLARE @E int=(SELECT v from N where n=@A),@F int=(SELECT v from N where n=@B)
DECLARE @C char(9) = (SELECT case D when 'D' then 'Dissonant' when 'C' then 'Consonant' END from D where v in(abs(@e-@f),12-abs(@e-@f)))
RETURN isnull(@C,'NotANote')
END
```
[Answer]
# [Perl 5](https://www.perl.org/), 106 bytes
```
("C,C#,D,D#,E,F,F#,G,G#,A,A#,B,"x2)=~/$F[0],(.*?)$F[1],/;$r=(1+($1=~y/,//))%12;say(grep/$r/,(0,3..5,7..9))
```
[Try it online!](https://tio.run/##Dca7CsIwGAbQV5EmQqJf8yeVIFKC1PQy@QTSoUMRQWxIHezSRzd6phPG@LQpiczDM9SoGRq0aBk6dAwVKoYLsk8h3Uq8vekeQu3O8l/Tg0oenTB7wY1bFwKRlFtTlPOwiHscA/FIEBoHpSyOSp2kTMlvmu8U3o/pNaf8apU2OuXDDw "Perl 5 – Try It Online")
Returns false for dissonant, true for consonant.
]