The trumpet is a valved aerophone instrument, usually pitched in B♭. The sound is made when the player vibrates their lips to displace air inside the instrument. That vibration is acquired by setting one's mouth in a specific way, called the embouchure. Different embouchures, with tighter or looser lips, produce different pitches.

Furthermore, each valve in the trumpet also changes the pitch of the instrument. When depressed, a valve closes a path inside the tubing of the instrument, making the air flow through a longer path, thus lowering the pitch of the original sound. For the purposes of this challenge, we'll consider the standard, B♭ trumpet, in which the first valve lowers the pitch by a full step, the second lowers the pitch by a half-step, and the third lowers the pitch by one and a half step.

The Challenge

Your challenge is to create a program or function that, given two inputs embouchure and valves, determines the pitch of the note being played.

For the purposes of this challenge, the notes will follow the sequence:

B♭, B, C, C♯, D, E♭, E, F, F♯, G, G♯, A.


  • I/O can be taken/given in any reasonable method.
  • Standard loopholes apply.
  • You're allowed to use b and # instead of and if you wish to.
  • Input for valves can be taken as a list of depressed valves (1, 3) or a boolean list (1, 0, 1).
  • This is , so shortest code in each language wins.

Test Cases:

Valves in these test cases is given as a boolean list, where 0 means depressed and 1 means pressed.

Embouchure:    Valves:   Output:
B♭             0 0 0     B♭
B♭             0 1 0     A
B♭             1 0 1     F
C♯             0 0 1     B♭
C♯             1 1 1     G
E♭             1 0 0     C♯
G              0 1 1     E♭
G♯             1 0 0     F♯
G♯             0 0 1     F
G              1 0 0     F
F♯             1 0 0     E
D              1 0 1     A
A              1 1 1     E♭
E              1 1 0     C♯
E              0 0 1     C♯

Disclaimer: I'm not much of a musician yet, so I do apologize for any butchering I might've made on the test cases. Corrections are appreciated.

  • 2
    \$\begingroup\$ Percussionist here. Wait wait, that's how you spell embouchure. Always thought it started with an a ;-) \$\endgroup\$
    – bren
    Commented Mar 15, 2018 at 14:39
  • 1
    \$\begingroup\$ @vasilescur you're right. I'll fix those and review any other possible mistakes. Thanks for the heads up. \$\endgroup\$
    – J. Sallé
    Commented Mar 15, 2018 at 15:44
  • 1
    \$\begingroup\$ As someone who's played trumpet a long time, I'm really confused by the Embouchure measurement... For example what is a C# Embouchure? \$\endgroup\$
    – bendl
    Commented Mar 15, 2018 at 18:39
  • 1
    \$\begingroup\$ Should F# 100 be E not F? \$\endgroup\$ Commented Mar 15, 2018 at 19:47
  • 2
    \$\begingroup\$ @bendl There's no such thing. You can't play a C# on a trumpet without pressing down any valves. Just specific notes (B♭-F-B♭-D-F-A♭-B♭...), the overtone series of B♭. Still, even if it doesn't reflect a real instrument the challenge is perfectly well defined. \$\endgroup\$
    – Chris
    Commented Mar 16, 2018 at 2:23

11 Answers 11


Python 3 2, 125 119 81 bytes

lambda e,f,s,t,n=2*'A G# G F# F E Eb D C# C B Bb'.split():n[n.index(e)+2*f+s+3*t]

Try it online!

Saved a lot of bytes thanks to Jonathan Allan.

My original solution (in Python 3):

n=2*'Bb B C C# D Eb E F F# G G# A'.split()

Try it online!

Saved 6 bytes thanks to @HyperNeutrino.


First, I make an array of notes, but doubled in length so I don't have to worry about looping around from Bb to A.

Then, I take input in the following format (for example):

Bb 1 0 1

I then find the index of the starting note using n.index(e,9) (the 9 is there to make sure that I start well in the middle of the (doubled) list. I calculate the desired offset with the expression:

2*int(f) - int(s) - 3*int(t)

Where f is the first valve, s is the second valve, and t is the third.

Finally, it simply prints the note found in the list by subtracting the offset from the starting index.

  • 3
    \$\begingroup\$ save a few bytes by separating by spaces. "<some string>".split() splits by whitespace by default \$\endgroup\$
    – hyper-neutrino
    Commented Mar 15, 2018 at 15:55
  • \$\begingroup\$ Save 30 bytes by moving to Python 2 (avoiding str and int casts and allowing evaluated input) and reversing the notes and offsetting forward (avoiding the ,9 in the index call. Try It Online! \$\endgroup\$ Commented Mar 15, 2018 at 22:32
  • \$\begingroup\$ ...and another 8 moving to function (which works in Python 2 or 3) Try It Online! \$\endgroup\$ Commented Mar 15, 2018 at 22:41
  • \$\begingroup\$ @JonathanAllan I learned several Python golfing tricks from your improvements. Thank you so much! \$\endgroup\$
    – vasilescur
    Commented Mar 16, 2018 at 12:23
  • \$\begingroup\$ ...in fact you can use the list in its original order without repetition and subtract values since the negative index never goes out of bounds (the most negative would be 'Bb', 1, 1, 1 taking you to index -6 which would be E, as required) - it's what TFeld has since done. \$\endgroup\$ Commented Mar 16, 2018 at 17:48

Wolfram Language (Mathematica), 100 bytes (and 134 for a working trumpet)


Try it online!

Quite straightforward.


A better output for the cost of 34 bytes.

  • \$\begingroup\$ Wait ... Mathematica has Audio output??? Wicked! \$\endgroup\$
    – Titus
    Commented Mar 16, 2018 at 12:41
  • \$\begingroup\$ Of course Mathematica has a built-in for audio output. This is gold. \$\endgroup\$
    – J. Sallé
    Commented Mar 16, 2018 at 13:14

Jelly,  37  36 bytes


A dyadic link accepting the valves as a list of 1s or 0s as a list representing [second, first, third] on the left and the embouchure as a list of characters on the right which returns a list of characters.

Try it online!


ØAḣ7;⁾#b“®JXrẊỤȥ’ṃnŒl$œṗ$Ḋ©i_⁸æ.J¤ị® - Link: list of integers, V; list of characters, E
ØA                                   - yield uppercase alphabet
  ḣ7                                 - head to index 7 = "ABCDEFG"
     ⁾#b                             - literal list of characters = "#b"
    ;                                - concatenate = "ABCDEFG#b"
        “®JXrẊỤȥ’                    - literal integer = 2270857278734171
                 ṃ                   - base decompress (i.e. convert to base 9 using the 'digits' "bABCDEFG#")
                                     -                 = "ABbBCC#DEbEFF#GG#"
                        $            - last two links as a monad:
                     $               -   last two links as a monad:
                   Œl                -     to lower case = "abbbcc#debeff#gg#"
                  n                  -     not equal? (vectorises) = [1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0]
                      œṗ             -   partition at truthy indices = [[],"A","Bb","B","C","C#","D","Eb","E","F","F#","G","G#"]
                         Ḋ           - dequeue = ["A","Bb","B","C","C#","D","Eb","E","F","F#","G","G#"]
                          ©          - copy to register and yield
                           i         - first index of E in there
                                 ¤   - nilad followed by links as a nilad:
                             ⁸       -   chain's left argument, V
                                J    -   range of length [1,2,3]
                              æ.     -   dot product (i.e. 1*second + 2*first + 3*third)
                            _        - subtract
                                   ® - recall from register
                                  ị  - index into (1-based and modular)

Ruby, 71 bytes

->e,(b,c,d){a=%w{Bb B C C# D Eb E F F# G G# A};a[a.index(e)-b*2-c-d*3]}

Try it online!

70 chars but 80 bytes

->e,(b,c,d){a="B♭BCC♯DE♭EFF♯GG♯A".scan /.\W?/;a[a.index(e)-b*2-c-d*3]}

Try it online!


Javascript 96 bytes

Following @vasilescur idea, this is the implementation in js



  • \$\begingroup\$ 3 bytes less ;) BTW the flats and sharps should be counted as 3 bytes aren't they? \$\endgroup\$ Commented Mar 16, 2018 at 2:49
  • \$\begingroup\$ Oh nvm (I didn't see that b and # are allowed) but you need to use b and # instead of flats and sharps. \$\endgroup\$ Commented Mar 16, 2018 at 2:55

Batch, 188 bytes

@set n=%1
@for %%n in (C.0 C#.1 D.2 Eb.3 E.4 F.5 F#.6 G.7 G#.8 A.9 Bb.10 B.11)do @if %%~xn==.%n% echo %%~nn

Uses # and b: this means that Eb and Bb are legal variable names; # is handled by doing a string replacement to +1. The result of the string replacement is then automatically evaluated and the valves are then taken into account before the result is looked up in a list.


Stax, 32 bytes


Run and debug it online

It takes a note name and a list of depressed valves. It builds an array of note names, then calculates the total valve interval, and gets the note at that offset in the array.

"AbABbBCC#DEbEFF#G" just a literal
{VA#}(Y             partition at capital letters and store in y
,]I                 get the index of the input note
,2R:t               swap 1s and 2s in valve list
{-F                 subtract valve list from note index
y@                  look up result from note array

Run this one


Python 2, 84 79 bytes

lambda e,a,b,c,s='Bb B C C# D Eb E F F# G G# A'.split():s[s.index(e)-2*a-b-3*c]

Try it online!


C (gcc), 92 86 82 bytes


Try it online!

Adapted from @Vazt's implementation.


Perl6/Rakudo 73 chars

Technically this is 83 bytes because I put the Unicode characters in, but swapping them for the ASCII equivalents would give 73 bytes.

As a {code block} with parameters like $^a this is a lambda, with a signature ($a, $b, $c, $d).

{$_=2*$^b+$^c+3*$^d;'AG♯GF♯FEE♭DC♯CBB♭'x 2~~/$^a(\w\W?)**{$_}/~~/\w\W?$/}

Call it:

say { ... }("D", 1, 0, 1)
>> A


sub f($a, $b, $c, $d) {
   my $totalShift = 2*$b + $c + 3*$d;
   my $doubledScale = 'AG♯GF♯FEE♭DC♯CBB♭' x 2;
   my $matchEmbOnward = $doubledScale ~~ / $^a (\w\W?)**{$totalShift} /;
   my $matchFinalNote = $marchEmbOnward ~~ / \w \W? $ /;
   return $matchFinalNote;

Here we double a string '...' x 2 using the x infix operator, then searching for the embouchure followed by n notes using the smartmatch operator '...' ~~ /.../ - the regex hinges on \w\W? which is a word char then maybe a non-word char.

We look for n instances of that via (\w\W?)**{$_}, where we've already calculated n=$_ from params $b to $d. This yields a match from the embouchure note to the resulting note, of which we just want the last so we match that with another ~~ /\w\W?$/.

The calculation of $_ first is necessary to permit $^b implicit param creation on the block.

76 chars

An alternative using an array rather than string matches is 3 more chars:

{$_=<B♭ B C C♯ D E♭ E F F♯ G G♯ A>;.[((.first: $^a,:k)-2*$^b-$^c-3*$^d)%12]}

Finding the embouchure in the list is achieved with @arr.first: $^a, :k, which returns the index (key) of the found element with :k.

Setting the array to $_ (as an object) lets us use .first and .[ ] on it without spending too many characters.


C (gcc), 155 bytes

char r[][12]={"bb","b","c","c#","d","eb","e","f","f#","g","g#","a"};u;v(z,y,x,w)char*z;{for(;u<12;u++)if(!strcmp(z,r[u]))break;u=u-2*y-x-3*w;u=u<0?12+u:u;}

Try it online!

Simple approach.

Valve input is 0,1.

Embouchure input must be lowercase. Interestingly, TiO is not finding strcmpi() without including string.h, whereas mingw-gcc allows it with the standard -Wimplicit-function-declaration warning.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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