Music Interval Solver

11

2

enter image description here

In music theory, an interval is the difference between two pitches. Each pitch is defined by the number of half-steps (The difference between C and C#) or whole steps (The difference between C and D). One whole step is the same as two half-steps. Here is a list of all the default intervals and the number of half-steps they represent:

0     Perfect Unison
2     Major Second
4     Major Third
5     Perfect Fourth
7     Perfect Fifth
9     Major Sixth
11    Major Seventh
12    Perfect Octave

There are 3 variations on the default intervals, minor, diminished, and augmented.

  • A minor interval is one half-step lower than a major interval, but not a perfect interval. So you have a minor second (1), a minor third (3), a minor sixth (8), and a minor seventh (10). There is no such thing as a minor fourth, minor fifth, minor unison or minor octave since these are all perfect intervals.

  • A diminished interval is one half-step lower than a minor or perfect interval. There is diminished Second (0), diminished third (2), diminished fourth (4), diminished fifth (6), diminished sixth (7), diminished seventh (9) and diminished octave (11).

  • An augmented interval is one half-step higher than a major or perfect interval. We have Augmented Unison (1), Augmented Second (3), Augmented third (5), Augmented Fourth (6), Augmented fifth, (8), Augmented sixth (10), and Augmented seventh (12).

The challenge:

You must write a program or function that takes a number of half steps or whole steps and then prints one of the valid English descriptions of this interval. It doesn't matter which description you pick, as long as it exactly matches the IO table. You can take this as one string

"5w" == 5 whole steps
"3h" == 3 half steps

or as a number and a string/char.

5, "w" == 5 whole steps
3, "h" == 3 half steps.

You can assume that every input will be between 0 and 12 half steps.

IO table

Here is a full list mapping the number of half-steps to all acceptable outputs.

0       Perfect unison, Diminished second   
1       Minor second, Augmented unison  
2       Major second, Diminished third  
3       Minor third, Augmented second   
4       Major third, Diminished fourth  
5       Perfect fourth, Augmented third     
6       Diminished fifth, Augmented fourth  
7       Perfect fifth, Diminished sixth 
8       Minor sixth, Augmented fifth        
9       Major sixth, Diminished seventh 
10      Minor seventh, Augmented sixth      
11      Major seventh, Diminished octave    
12      Perfect octave, Augmented seventh   

Here is some sample I/O:

5w      Minor Seventh
5h      Augmented Third
12h     Perfect Octave
12w     UNDEFINED
1w      Diminished third
2h      Major Second

James

Posted 2016-03-24T04:43:03.647

Reputation: 54 537

Dimished?.... – CalculatorFeline – 2016-03-24T05:02:30.830

7@CatsAreFluffy My poor spelling has dimished my ability to write good challenges. ಠ_ಠ – James – 2016-03-24T05:04:20.360

Still a good challenge, just with more edits! :P – Rɪᴋᴇʀ – 2016-03-26T01:19:48.843

Answers

1

Ruby, Rev B 138 bytes

->n,s{i=12-n-n*(s<=>?h)
[a='Augmented','Major','Minor',d='Diminished',a,'Perfect',d][i%7]+' '+%w{seventh fifth third unison}[i%7/4+i/7*2]}

5 bytes saved by not repeating Augmented/Diminished. 1 byte saved by use of ?h.

Ruby, Rev A 144 bytes

->n,s{i=12-n-n*(s<=>'h')
%w{Augmented Major Minor Diminished Augmented Perfect Diminished}[i%7]+' '+%w{seventh fifth third unison}[i%7/4+i/7*2]}

The idea is to minimise the number of basic intervals (seventh fifth third and unison only) and take advantage of the fact that sevenths and fifths have an analogous relationship to that between thirds and unisons.

There are four types of seventh/third and 3 types of fifth/unison so the index variable i is set to 12 minus the number of half steps, so that the first term of the expression i%7/4 + i/7*2 will correctly select the type of basic interval.

ungolfed in test program

f=->n,s{                 #n = number of steps. s= step size, w or h
  i=12-n-n*(s<=>'h')     # i=12-n. If s is later in the alphabet than 'h' subtract again for whole steps
  %w{Augmented Major Minor Diminished Augmented Perfect Diminished}[i%7]+
  ' '+%w{seventh fifth third unison}[i%7/4+i/7*2]
}

-1.upto(12){|j|
puts f[j,'h']
}  

0.upto(6){|j|
puts f[j,'w']
}

output

Diminished unison
Perfect unison
Augmented unison
Diminished third
Minor third
Major third
Augmented third
Diminished fifth
Perfect fifth
Augmented fifth
Diminished seventh
Minor seventh
Major seventh
Augmented seventh

Perfect unison
Diminished third
Major third
Diminished fifth
Augmented fifth
Minor seventh
Augmented seventh

Undefined behaviour inputs: The function gives the correct answer of diminished union for -1 halfsteps, but fails for inputs over 12. For example, it outputs perfect unison for 14 half steps, as the algorithm is based on a cycle of 14 rather than 12.

Level River St

Posted 2016-03-24T04:43:03.647

Reputation: 22 049

2

Python 2.7, 155 bytes

s='second unison third fourth sixth fifth seventh octave Diminished Augmented'.split()
def f(n,c):x=0xDE9CB87561430>>[4,8][c>'h']*n;print s[x%2+8],s[x/2%8]

Ken 'Joey' Mosher

Posted 2016-03-24T04:43:03.647

Reputation: 136

2

Python 2, 149 bytes

def f(n,c):n*=1+(c>'h');print(n-6)%13%2*"Diminished"or"Augmented",'octave seventh sixth fifth fourth third second unison'.split()[71056674174>>3*n&7]

First, whole steps are converted to half steps.

Then, Diminished vs Augmented is printed. These alternate for adjacent n except that n=5 and n=6 give the same, which is achieved by first putting them across a boundary modulo an odd number.

Finally, the distance is printed, computed via a three-bit lookup table. This is shorter than doing int('6746543230210'[n]).

xnor

Posted 2016-03-24T04:43:03.647

Reputation: 115 687

1

Retina, 153 bytes

\d+
$*
(.*)w|h
$1$1
^1*$
$.0
^[02479]|11
Diminished $0
^\d
Augmented $0
10|7
sixth
11
octave
12|9
seventh
8
fifth
4|6
fourth
5|2
third
1
unison
\d
second

Input number is first converted to unary, then doubled if followed by w, and any letters are removed, leaving only the unary number. This number is then converted back to decimal. Finally, some search and replace is applied to construct the final output.

Example runs:

6w => 111111w  => 111111111111 => 12 => Augmented 12 => Augmented seventh
7h => 1111111h => 1111111      => 7  => Diminished 7 => Diminished sixth
3w => 111w     => 111111       => 6  => Augmented 6  => Augmented fourth
0h => h        =>              => 0  => Diminished 0 => Diminished second

Try it online!

daavko

Posted 2016-03-24T04:43:03.647

Reputation: 824

0

Vitsy, 166 bytes

Well, this can definitely be further golfed.

WW2M1+*a+mZ
'dehsinimiD'
'roniM'
'rojaM'
'tcefreP'
'detnemguA'
'dnoces '
'htruof '
'htxis '
'evatco '
6m1m
6m2m
6m3m
6m5m
7m1m
7m4m
7m5m
8m1m
8m2m
8m3m
8m5m
9m1m
9m4m

This works by defining the minimal amount of items possible, then calling those items through the method syntax.

Try it Online!

Addison Crump

Posted 2016-03-24T04:43:03.647

Reputation: 10 763

0

Java, 225 224 bytes

There has got to be a better way to pack these strings but I don't have any ideas.

(i,s)->{String A="Augmented",M="Major",m="Minor",P="Perfect",D="Diminished",d=" Second",f=" Fourth",a=" Sixth",C=" Octave";String[]o=new String[]{D+d,m+d,M+d,A+d,P+f,A+f,D+a,m+a,M+a,A+a,D+C,P+C};i*=s=='w'?2:1;return o[i-1];}

Indented:

static BiFunction<Integer, Character, String> interval = (i,s) -> {
    String A="Augmented",M="Major",m="Minor",P="Perfect",D="Diminished",
            d=" Second",f=" Fourth",a=" Sixth",C=" Octave";
    String[] o = new String[] {D+d,m+d,M+d,A+d,P+f,A+f,D+a,m+a,M+a,A+a,D+C,P+C};
    i *= s=='w' ? 2 : 1;
    return o[i-1];
};

CAD97

Posted 2016-03-24T04:43:03.647

Reputation: 1 367

I believe you can shorten it by replacing if(s=='w')i*=2; with i*=s=='w'?2:1; – Mr Public – 2016-03-28T12:54:39.960

@MrPublic You are correct. – CAD97 – 2016-03-28T12:59:36.860

0

Javascript 189 bytes

a=>(n='sutsftfxFvxov'[N=parseInt(a)*(a.slice(-1)>'v'?2:1)])&&((N>5?N+1:N)%2?'Augmented ':'Dimished ')+'unison,second,third,fourth,fifth,sixth,seventh,octave'.split`,`['ustfFxvo'.indexOf(n)]



 F=
  a=>
    (n='sutsftfxFvxov' //using the right side of the possible answers
                       //set n = the letter representing
                       //unison, first, second ...

       //set N to 12 for 12h, but 24 for 12w
       [N=parseInt(a)*(a.slice(-1)>'v'?2:1)])

  &&   //if we were out of range (12w) we'll return undefined


    (
      (N>5?N+1:N)%2?  //get Aug or Dim (right side goes)
                      //DADADAADADADA
                      //     ^^ makes this a pain
       'Augmented ':'Dimished '
     )
     +
            //turn n (which is u for unison, x for sixth, etc
            //into it's full name
       'unison,second,third,fourth,fifth,sixth,seventh,octave'
         .split`,`
     ['ustfFxvo'.indexOf(a)]

Charlie Wynn

Posted 2016-03-24T04:43:03.647

Reputation: 696