7
\$\begingroup\$

For this challenge, you need to print out the fingerings for various brass instruments.

The notes an instrument can play (as well as their fingerings) are listed below:

    Cornet                       Baritone
    Trumpet  Bugle  French Horn  Euphonium  Tuba
A#0                                         0
B0  
C1                                          1234
C#1                                         134
D1                                          234
D#1                                         14
E1                                          24
F1                                          4
F#1                                         23
G1                                          12
G#1                                         1
A1                                          2
A#1                              0          0
B1                  123          1234       24
C2                  13           134        4
C#2                 23           234        23
D2                  12           124        12
D#2                 1            14         1
E2                  2            24         2
F2                  0            4          0
F#2                 123          23         23
G2                  13           12         12
G#2                 23           1          1
A2                  12           2          2
A#2                 1            0          0
B2                  2            24         12
C3                  0            4          1
C#3                 23           23         2
D3                  12           12         0
D#3                 1            1          1
E3  123             2            2          2
F3  13              0            0          0
F#3 23              12           23         23
G3  12              1            12         12
G#3 1               2            1          1
A3  2               0            2          2
A#3 0               1            0          0
B3  123             2            12         12
C4  13              0            1          1
C#4 23              23           2          2
D4  12              12           0          0
D#4 1               1            1          1
E4  2               2            2          2
F4  0               0            0          0
F#4 23              2            23         23
G4  12       0      0            12         12
G#4 1               2            1          1
A4  2               0            2          2
A#4 0               1            0          0
B4  12              2            12
C5  1        0      0            1
C#5 2               23           2
D5  0               12           0
D#5 1               1            1
E5  2        0      2            2
F5  0               0            0
F#5 23
G5  12       0
G#5 1
A5  2
A#5 0

Input

  • A single string with a name of an instrument. You can assume the name will always be one of the 7 listed above.
  • A note, which can be a single string or a string and integer. You can assume the note will match one of the notes listed above.

Output

  • The fingering for the note on that instrument. This can either be a list of integers (one for each digit), or a single integer.
  • If the instrument cannot play a given note (listed as blank above), return "Impossible"

Test Cases

Cornet D#3        Impossible
Cornet E3         123
Trumpet G4        12
Trumpet B4        12
Trumpet F#5       23
Bugle F#5         Impossible
Bugle G5          0
Bugle G1          Impossible
French Horn B1    123
French Horn C3    0
French Horn E5    2
French Horn A#5   Impossible
Baritone A#5      Impossible
Baritone A#2      0
Baritone B2       24
Baritone B1       1234
Euphonium F2      4
Tuba A#0          0
Tuba B0           Impossible
Tuba C1           1234
Tuba B1           24
Tuba G#4          1
Tuba B4           Impossible

Notes

  • Trumpet and Cornet have the same fingerings, as well as Baritone and Euphonium
  • These ranges aren't comprehensive. I've tried to stick to the "standard" notes, but instruments can often go below (pedal notes) or above.
  • The notes listed are in concert pitch
  • You'll notice that there are a lot of patterns between the fingerings. Finding those patterns is critical to golfing this well.

This is a , so the shortest answer in your favorite language wins!

\$\endgroup\$
  • \$\begingroup\$ This is the kind of weird info you learn on PPCG. The only wind instrument I play is tin whistle, but I understand the brass valves work as follows: valve 2 =-1 semitone, valve 1=-2 semitones, valve 3=-3 semitones, valve 4=-5 semitones. I find it odd that the tuba is different from the euphonium, I would think the fingerings should be the same, just an octave down. I think the blank line should be removed and a 124 inserted at the appropriate place. Am I right? \$\endgroup\$ – Level River St Jan 16 '16 at 21:24
  • \$\begingroup\$ A little research shows it depends if your tuba is compensating or noncompensating. I am correct for a compensating tuba. norlanbewley.com/tuba/fingering-tuba-1.htm shows the B is indeed missed for a noncompensating tuba, though he skips a 14 instead of 124 at the D. It seems like basically you're tuning on the fly with the embocouchure. This question has given me more respect for tuba players! I guess we stick with the question as written then. \$\endgroup\$ – Level River St Jan 16 '16 at 21:49
  • \$\begingroup\$ @steveverrill I was literally in the middle of saying that very thing :) \$\endgroup\$ – Nathan Merrill Jan 16 '16 at 21:52
  • 3
    \$\begingroup\$ Oh another minor point: Normally the octave changes number between B and C, not between G and A. In reality all your A's and B's should be an octave lower than you have written them. Are you going to correct it, or leave it as it is? (easier to golf as it is.) \$\endgroup\$ – Level River St Jan 17 '16 at 0:07
  • \$\begingroup\$ @steveverrill welp, my bad. I have no idea how I didn't know that, as I have taken music theory courses. \$\endgroup\$ – Nathan Merrill Jan 17 '16 at 5:09
2
\$\begingroup\$

Ruby, 292

->i,n{t='nberlu'.index(i[-2])%5
u,v=t<2?[4,24]:[13,123] 
a=[]
'!&)+-259>EQR'.tr(?+,t==3??+:?)).bytes{|i|a[i,1]=[0,2,1,12,23,u,v,14,124,234,134,1234]}
p=n[0].ord*13/8%12+n[-1].to_i*12+n.size
p<17&&p-=1
f=a[x='i]udw'[t].ord-p]
('&!-!2'[t]..'QRKK>'[t])===x.chr&&p!=12&&(t<4||1>f)?f:"impossible"}

Explanation

The table below shows more clearly the similarities and differences between the instruments. Basically, a fingering of 0 corresponds to one of the harmonics of the main tube. Not all harmonics are available on all instruments. For example the French horn is the only one to use the 9th harmonic. Differences are apparent by spaces in the table, or highlighted with *

The bugle is simplest and has no valves. The other instruments have at least 3 valves. Valves are used to add bits of tube to the basic instrument to lower the pitch. Valve 2=-1 semitone, Valve 1=-2 semitones, Valve 3=-3 semitones, and valve 4 (if present) is -5 semitones. Valve 4 extends the range of the lower instruments, and is also used as an alternative fingering 4 or 24 for notes which are fingered as 13or 123 on instruments without a 4th valve.

All the notes from a particular harmonic downwards are fingered in the same way, up until the next harmonic down is reached. The harmonics are quite closely spaced in the upper range, but get sparser in the lower range. At the start of the code a table is built from the highest harmonic downwards by repeatedly inserting a complete set of 12 fingerings into the array. Some fingerings are unused because another harmonic is encountered before the lower fingerings are required. This data is not overwritten, it is pushed to the end of the array, so the end of the array contains a lot of garbage, but this does not matter.

Then all we have to do is transpose the input to the right place on the table and return the fingering. Also, we have to check if the note is in range. Rather than do this with the note itself, I do it with the position in the table of fingerings. This uses a more limited range of values.

   Corn         Bari                
   Trum Bug HornEuphTuba            
No                      ASC char    harmonic

49                  0   82  R   fundamental (repeat for tuba)
48              0   0   81  Q   fundamental (not available on tuba)
47              12341234            
46              134 134         
45              234 234         
44              124             
43              14  14          
42  123*    123*24  24          
41  13*     13* 4   4           
40  23      23  23  23          
39  12      12  12  12          
38  1       1   1   1           
37  2       2   2   2           
36  0       0   0   0   69  E   2nd harmonic
35  123*    123*24  24          
34  13*     13* 4   4           
33  23      23  23  23          
32  12      12  12  12          
31  1       1   1   1           
30  2       2   2   2           
29  0   0   0   0   0   62  >   3rd harmonic
28  23      23  23  23          
27  12      12  12  12          
26  1       1   1   1           
25  2       2   2   2           
24  0   0   0   0   0   57  9   4th harmonic
23  12      12  12  12          
22  1       1   1   1           
21  2       2   2   2           
20  0   0   0   0   0   53  5   5th harmonic
19  1       1   1   1           
18  2       2   2   2           
17  0   0   0   0   0   50  2   6th harmonic
16  23      23  23  23          
15  12      12  12  12          
14  1       1   1   1           
13  2       2   2   2           
12  0       0   0   0   45  -   8th harmonic
11          2*  12  12          
10          0*  1   1   43  +   9th harmonic
9           2   2   2           
8           0   0   0   41  )   10th harmonic
7           1   1   1           
6           2   2   2           
5           0   0   0   38  &   12th harrmonic
4           23      23          
3           12      12          
2           1       1           
1           2       2           
0           0       0   33  !   16th harmonic

commented in test program

#penultimate letter of instrument
                    range     16th harmonic
#n 0 baritone       A#1-F5    A#5
#b 1 tuba           A#0-A#4   A#4
#e 2 trumpet,cornet E3-A#5    A#6
#r 3 french horn    B1-F5     F5
#l 4 bugle          G4-G5     C7
#u 0 euphonium
g=->i,n{
  t='nberlu'.index(i[-2])%5                  #translate instrument into code above according to penultimate letter of name
  u,v=t<2?[4,24]:[13,123]                    #select fingerings for 4 valve or 3 valve instruments
  a=[]                                       #empty fingerings table
  '!&)+-259>EQR'.                            #list of harmonics as ascii codes + =9th harmonic, only on french horn
    tr(?+,t==3??+:?)).                       #if not french horn, delete the + and replace with duplicate of symbol before it )
      bytes{|i|a[i,1]=                       #for each value in the string, insert a complete table of 12 fingerings into a,
       [0,2,1,12,23,u,v,14,124,234,134,1234]}#pushing garbage fingerings to the end
   p=n[0].ord*13/8%12+                       #pitch of note depends on note name
     n[-1].to_i*12+n.size                    #+12*octave number. Length of string is 1 longer for sharp, so add this also.
   p<17&&p-=1                                #for tuba, consider pitch lowered by 1 if below D#1 to skip over the 124 fingering
   f=a[x='i]udw'[t].ord-p]                   #subtract p from 'i]udw'[t].ord to find x, the position of the fingering in the table. Assign the actual fingering to f 
   ('&!-!2'[t]..'QRKK>'[t])===x.chr&&        #if x is in the range for the instrument
     p!=12&&                                 #and the note is not B0 (missing for tuba, completely out of range for other instruments)
    (t<4||1>f)?                              #and the instrument is not a bugle (or if it is, the fingering is 0)
      f:"impossible"                         #return the fingering. Otherwise return impossible.
}


[['Cornet','D#3'],       #Impossible 
['Cornet','E3'],         #123
['Trumpet','G4'],        #12 
['Trumpet','B4'],        #12 
['Trumpet','F#5'],       #23 
['Trumpet','A#5'],        #0
['Trumpet','B5'],         #Impossible

['Bugle','F#5'],         #Impossible
['Bugle','G5'],          #0
['Bugle','G1'],          #Impossible
['Bugle','C4'],           #Impossible
['Bugle','G4'],           #0
['Bugle','C6'],           #Impossible


['French Horn','A#1'],    #Impossible
['French Horn','B1'],    #123
['French Horn','C3'],    #0  
['French Horn','E5'],    #2 
['French Horn','F5'],     #0
['French Horn','F#5'],    #Impossible
['French Horn','A#5'],   #Impossible

['Baritone','A#5'],      #Impossible
['Baritone','A#2'],      #0 
['Baritone','B2'],       #24 
['Baritone','A1'],        #Impossible
['Baritone','A#1'],       #0
['Baritone','B1'],       #1234 
['Euphonium','F2'],      #4 
['Euphonium','F5'],       #0
['Euphonium','F#5'],      #Impossible  

['Tuba','A#0'],          #0
['Tuba','B0'],           #Impossible
['Tuba','C1'],           #1234
['Tuba','C#1'],           #134
['Tuba','D1'],            #234
['Tuba','D#1'],           #14
['Tuba','B1'],           #24
['Tuba','G#4'],          #1
['Tuba','A#4'],           #0
['Tuba','B4']].each{|c|  #Impossible
  puts c
  puts g[c[0],c[1]]
  puts
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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