I want to make a C program which randomly selects 6 numbers from numbers the range 1 - 37, without repeating any previously permutations. For example, suppose the program randomly selects 1,2,3,4,5,6. If the next permutation is randomly selected as 2,1,3,4,5,6, then that is OK. However, if 1,2,3,4,5,6 is selected again, that this is not OK. I want this to continue until there are no more possible sets available. How would I go about writing this C program?
I want to make a C program which randomly selects 6 numbers from numbers
Share
Now the KNUTH shuffle answer posted below is quite elegant. But it doesn’t meet a particular requirement set forth by the OP in his question.
The OP said he wanted to be able to select all sets in random order until his program has consumed them all. So here goes. For purposes of demonstrate, we’ll understand “select” to mean “print”.
The total number of possible sets of “6 unique digits in the range of 1-37” can be expressed as:
1673844480 (1.6 billion) fits nicely within a signed 32-bit number. And every unique set could potentially be assigned a unique integer id.
So… if you can generate a random number between [0,1673844479], we can map that to a very specific set of 6 unique integers.
To construct the set, we’ll need a helper function that will allow us to keep track of which values between 1-37 have already been used during the iteration process of constructing the set. Then a little modulo arithmetic math to help us map an ID number to it’s set of 6-digits:
And just to prove that this works, we can have another function iterate over all sets:
Now the program above will print out all the sets starting from:
And ending with
And then obviously to print a random set:
But the OP wanted all sets printed in random order without repeats. This gets tricky, because we have to keep track of random number values previously generated. I can think of several ways to do this. The most obivous candidate solution is to keep a bitmask comprised of TOTAL_NUMBER_OF_SETS bits. That is:
That’s about 200MB of memory allocated. Large, but workable. Then we keep picking random numbers from the range [0-TOTAL_NUMBER_OF_SETS), checking the bitmask if it’s already been used, then call PrintSet with the random number after setting its bitmask position. Repeat until all TOTAL_NUMBER_OF_SETS have been printed.
Pseudo code for a working, yet problematic solution
Now this should work just fine. But it’s going to get dog-slow as the bitmask array starts to get filled up. The later iterations will spend most of its time just scanning the array of bits looking for an unset index value. There have been other discussions on StackOverflow on how to do efficient and uniform permutations of large sets. Perhaps a database is warranted. Go search for those solutions and apply it here for the win.