Probability that notes are in the same scale What is the probability that a random sequence of notes (on the 12-note chromatic scale) of length n is in the same major scale?
Quite some time ago, I came across a song written by converting pi to base-12. (The song didn’t go on forever, obviously, but it was really cool.) The guy who wrote the song claimed that pi is a “musical number”.
I wanted to make it a project to figure out whether pi is truly a musical number. That is, if pi in base-12 begins with a string of digits that, when converted to musical notes, stay in the same scale longer than statistically expected.
This is a big topic depending on what types of scale(s) one could choose and what key transitions would be allowable, but I thought major would be a good place to start.
Haven’t gotten very far mathematically, mainly because I can’t figure out exactly what to do or whether this is an easy or difficult problem.
Edit: Since I saw this in the comments—which scale is not specified in advance. So you have the notes, and then you see if they fit ANY scale.
 A: Having run a simulation, I am finding an average run of $4.69086$ notes all able to be said to stay in the same major key having run over 10 million trials... with a standard deviation of around $2.327$.  That said, the initial string of digits of $\pi$ in base 12 is not significantly more than the average.
Here is my javascript code.  Note, I use a few custom methods for looping over objects and cloning and removing.  It should be clear what they do
//Generate the scales
majorscale = [0,2,4,5,7,9,11];
majorscales = [];
for (i=0; i<12;i++){cur = []; 
  majorscale.$each(function(i){cur.push((i+1)%12)}); 
  majorscale = cur; majorscales.push(cur)}

//Define a function to generate a random song, length 25 is probably fine
generateSong = function(){song = []; for(i=0;i<25; i++){song.push(Math.floor(Math.random()*12))}; 
  return song}

//Define a function to find the length of a run in the same key
testLength = function(song,dbug){if (dbug){console.log(song)}; 
  //Scales not yet disqualified stored in remainingScales
  remainingScales = majorscales.$clone();  
  len = 0; 
  //Loop until all scales disqualified
  while(remainingScales.length){
    clone = remainingScales.$clone(); 
    if(dbug){console.log(song[len]); 
      console.table(clone)} 
    remainingScales.$each(function(scale){if(!scale.contains(song[len])){
      //If current note in song does not appear in a remaining scale, disqualify it
      //modify the clone so as to not mess up where we are in the loop and skip a scale
      clone.$remove(scale)}}); 
    remainingScales = clone; 
    len=len+1} 
  return len-1} //Off by one

//Run simulation
tot=0; for(i=0; i<10000000; i++){tot = tot + testLength(generateSong())};
console.log("Average: " + (tot/10000000))
tot2=0; for(i=0; i<10000000; i++){tot2 = tot2 + (testLength(generateSong())-tot/10000000)**2};
console.log("Std dev: " + Math.sqrt(tot2/10000000))

