randomHat

A random function that chooses every number from a "hat" before repeating

/* RandomHat
  Paul Badger 2007 - updated for Teensy compile 2017
  choose one from a hat of n consecutive choices each time through loop
  Choose each number exactly once before reseting and choosing again
*/

#define randomHatStartNum 10  // starting number in hat
#define randomHatEndNum 25    // ending number in hat - end has to be larger than start  
#define numberInHat (randomHatEndNum - randomHatStartNum) + 1

void setup()
{
  Serial.begin(9600);
  Serial.println("start ");
}

void loop()
{ // randomHat test
  for (int i = 1; i <= numberInHat; i++) {
    int x = randomHat();
    Serial.print(x);
    Serial.print(", ");
    delay(50);
  }
  Serial.println(" ");
}


int randomHat() {
  int thePick;		//this is the return variable with the random number from the pool
  int theIndex;
  static int currentNumInHat = 0;
  static int randArray[numberInHat];

  if  (currentNumInHat == 0) {                  // hat is emply - all have been choosen - fill up array again
    for (int i = 0 ; i < numberInHat; i++) {    // Put 1 TO numberInHat in array - starting at address 0.
      if (randomHatStartNum < randomHatEndNum) {
        randArray[i] = randomHatStartNum + i;
      }
    }
    currentNumInHat = abs(randomHatEndNum - randomHatStartNum) + 1;   // reset current Number in Hat
    // Serial.print(" hat is empty ");
    // if something should happen when the hat is empty do it here
  }

  theIndex = random(currentNumInHat);	                 //choose a random index from number in hat
  thePick = randArray[theIndex];
  randArray[theIndex] =  randArray[currentNumInHat - 1]; // copy the last element in the array into the the empty slot
  //                                                     // as the the draw is random this works fine, and is faster
  //                                                     // the previous version. - from a reader suggestion on this page
  currentNumInHat--;    // decrement number in hat
  return thePick;
}


added 2010-10-30.

A speed up of the reshuffling of the array at the end. Change

  for (i = theIndex; i<= (currentNumInHat - 1); i++){
    randArray[i] =  randArray[i + 1];           // bump all the higher array contents down one,  erasing the last number chosen
  }

in

  randArray[theIndex] =  randArray[currentNumInHat-1];

The idea is that the slot at theIndex becomes free and we just copy the last element from the array to that 'empty' slot. As the draw must be random this does not interfere.


Function Library

Share