How to create a random number x times and only show it once

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • frank lamarca

    How to create a random number x times and only show it once

    I have the random number generator that works but the some numbers repeat. I want to create 26 numbers between 1 and 26 and each number can only be used once.

    Code:
        srand((unsigned)time(0)); 
        int randNum=1; 
        for(int amtNum=0; amtNum<26; amtNum++)
        { 
                
        randNum = (rand()%26)+1;  // makes random number from 1 to 26
        
        cout << randNum << endl;
  • donbock
    Recognized Expert Top Contributor
    • Mar 2008
    • 2427

    #2
    Perhaps the simplest approach is to keep track of the numbers you already have. Each time you get a new random number check to see if it is one you already have. If it is, then discard it and loop back and try again.

    Somewhat more complicated would be to start with a pool of 26 numbers. Pick a 1-in-26 random value and use it as an index into the pool. You now are left with a pool of 25 values. Pick a 1-in-25 random value. Repeat until you're done. No need to do a final pick when the pool has only one value in it.

    This more complicated approach will complete in precisely 26 equal-size steps. The simpler approach will take progressively longer -- you will find yourself spending more and more time discarding repeated values.

    Comment

    • ADezii
      Recognized Expert Expert
      • Apr 2006
      • 8834

      #3
      I'm on the other side of town in the Access Forum, and I accidentally came across this Thread. I created an Algorithm many years ago in Visual Basic that will accomplish exactly what you are requesting. It is portable, and should easily be converted to any language (C in this case). The General Logic is as follows:
      1. Generate a Random Number of Values as defined by the CONSTANT conNUM_OF_VALUE S (in your case, 26).
      2. Populate an Array with these Randomly Generated Values between 1 and conNUM_OF_VALUE S.
      3. Iterate through this Array via 2 Nested Loops checking every Value in the Array against itself, except for equivalent Indexes.
      4. Repeat this process as long as Duplicate(s) exist.
      5. Output the results to the Immediate Window.
      6. I normally do not like the idea of using Unconditional Branching with GoTo outside of Error Trapping, but it seems to work well in this case. This Logic can easily be replace with a variation of the Do...Loop Structure using a Boolean Variable to check for Duplication.
      7. The Logic seems to work quite well with a small number of Randoms, but has never been tested with a larger amount.
        Code:
        'Array to hold Randomly Generated Numbers
        Dim aintRndNums() As Integer
        Const conNUM_OF_VALUES As Integer = 26      'Assume Ranges starts at 1 (1 to 26)
        ReDim aintRndNums(1 To conNUM_OF_VALUES)    'Redimension appropriately
        Dim intCtr As Integer                       'Counter for Loops
        Dim intCtr_2 As Integer                     'Counter for Loops
        
        Randomize   'Seed the Random Number Generator
        
        'Poppulate Array with conNUM_OF_VALUES Randomly Generated Numbers
        'between 1 and conNUM_OF_VALUES
        For intCtr = 1 To conNUM_OF_VALUES
          aintRndNums(intCtr) = Int(Rnd() * conNUM_OF_VALUES + 1)
        Next intCtr
        
        'Lets eliminate the Duplicates
        DoItAllOverAgain:
        For intCtr = 1 To UBound(aintRndNums)
          For intCtr_2 = 1 To UBound(aintRndNums)
            If intCtr <> intCtr_2 Then      'Check each Element against every other
                                            'Element except itself for Dups
              If aintRndNums(intCtr) = aintRndNums(intCtr_2) Then    'a Dup, get a New Random
                aintRndNums(intCtr) = Int(Rnd() * conNUM_OF_VALUES + 1)
                  GoTo DoItAllOverAgain
              End If
            End If
          Next intCtr_2
        Next intCtr
        
        'For Verification purposes
        For intCtr = 1 To conNUM_OF_VALUES
          Debug.Print aintRndNums(intCtr)
        Next intCtr
      8. OUTPUT:
        Code:
         10 
         23 
         1 
         4 
         20 
         25 
         15 
         22 
         18 
         14 
         8 
         9 
         21 
         11 
         5 
         12 
         19 
         17 
         2 
         24 
         26 
         7 
         13 
         6 
         16 
         3

      Comment

      • Geocool
        New Member
        • Oct 2010
        • 2

        #4
        Well, what i did was to create a bool array and check every time if number was used in a while statement.
        Check bellow.
        _______________ _______________ ______________

        Code:
        #include <iostream>
        #include <time.h>
        
        using namespace std;
        
        const int MAX_NUM(26);
        
        class RANDOM_NUM{
        public:
            void CreateRandNum();
            void SetNumsUnused();
            bool CheckIfAllUsed();
            int GetRandNum();
        private:
            bool numberUsed[MAX_NUM];
            int randNum;
        };
        
        void RANDOM_NUM::CreateRandNum()
        {
                bool numIsUsed(true); 
        
                do{
                    randNum = (rand()%26)+1; 
                    if(!numberUsed[randNum-1]) // if number is not used exit statement  and set it to used.
                    {
                        numberUsed[randNum-1] = true;
                        numIsUsed=false;
                    }
        
                }while(numIsUsed);
        }
        
        bool RANDOM_NUM::CheckIfAllUsed()
        {
                for(int i=0;i<MAX_NUM;i++)
                {
                    if(!numberUsed[i]) // if a number is not used it returns false.
                        return false;
                
                }
        
                return true;
        }
        
        void RANDOM_NUM::SetNumsUnused()
        {
            for(int i=0;i<MAX_NUM;i++)
                numberUsed[i] = false;
        }
        
        int RANDOM_NUM::GetRandNum()
        {
            return randNum;
        }
        
        int main(int argc,char *argv)
        {
             srand((unsigned)time(0)); 
            RANDOM_NUM randomNum;
            randomNum.SetNumsUnused();
        
            while(!randomNum.CheckIfAllUsed())
            {
                randomNum.CreateRandNum();
                cout << "Random Number: " << randomNum.GetRandNum() << endl;
            }
            getchar();
            return 0;
        }
        I just wrote and test the above code and it works. I hope it helps ;)
        oh and if u are using pure C change cout to printf and class to structure XD, i think the other stay the same ? Anyone correct me if I am wrong..

        Comment

        Working...