Generate random numbers without repeats - arrays

I want to generate random numbers without repeats till all gone, then again generating random numbers with the initial dataset.
I know keeping already generated numbers in an array and loopin through them to check whether it is alredy generated or the method deducting the numbers that are generated from the array and randomize numbers with the new array.
What I want is not those methods, if there is a way that is efficient using data structures will be quite nice, if it is any other method also ok
Thanks

Say you want to generate 1,000 unique random numbers and present them to some code one at a time. When you exhaust those numbers, you want to present the same numbers again, but in a different sequence.
To generate the numbers, use a hash table. In C#, it would look like this:
const int MaxNumbers = 1000;
HashSet<int> uniqueNumbers = new HashSet<int>();
Random rnd = new Random();
// generate random numbers until there are 1000 in the hash table
while (uniqueNumbers.Count < MaxNumbers)
{
uniqueNumbers.Add(rnd.Next());
}
// At this point you have 1,000 unique random numbers
// Put them in an array
int[] myNumbers = uniqueNumbers.ToArray();
This works because the HashSet.Add method rejects duplicates. And it's very fast because lookup in the hash table is O(1).
Now, you can serve them by setting a current index at 0 and increment it every time a number is requested. Something like:
int ixCurrent = 0;
int GetNextNumber()
{
if (ixCurrent < MaxNumbers)
{
++ixCurrent;
return myNumbers[ixCurrent-1];
}
But what to do when ixCurrent runs off the end of the array? Enter the Fisher-Yates Shuffle:
// out of numbers. Shuffle the array and return the first one.
for (int i = MaxNumbers-1; i > 0; --i)
{
int j = rnd.Next(i+1);
int temp = myNumbers[i];
myNumbers[i] = myNumbers[j];
myNumbers[j] = temp;
}
ixCurrent = 1;
return myNumbers[0];
}
If you know that the numbers you want to return are within a particular range (that is, you want to return the numbers 0-999 in random order), then you just fill an array with the values 0-999 and shuffle it.

I'm not sure what language you are using, but here's some C++ code that does what you're looking for. Instead of it searching an array, it just does a direct check of a specific section of memory for a set flag and if it isn't set then the number chosen is new and printed.
The section I marked as handler is the code that is first executed when a unique number is found. Change the 10's and the 11 to different numbers if you want a larger set of random numbers but you might have to wait forever for the output.
int main(int argc, char *argv[]){
char randn[10];
char randnset[10];
int n;
int ct=0;
memset(randnset,'1',10);
memset(randn,0,10);
while (ct < 10){
srand(time(NULL));
n=rand() % 11;
if (!randn[n]){
printf("%d\n",n); // handler
randn[n]='1';
ct++;
}
}
return 0;
}

Every random generator function takes a seed value as a parameter and uses it in its internal algorithm to generate random numbers. If you want to generate the same sequence of numbers, you have to use the same seed value. As an example you can achieve this in Java like this:
int seed = 10;
Random r = new Random(seed);
for(int i=0; i<10; i++){
System.out.println(r.nextInt());
}
The output is something like this (of course it will have different results in your system):
-1157793070
1913984760
1107254586
1773446580
254270492
-1408064384
1048475594
1581279777
-778209333
1532292428
and it gives me the same results each time I execute it.

Related

how can i make two equal random numbers in c

I'm new to coding and i need help with my project: so, what i need to do is code a "finding the two same cards game", in which every card has a number and we're basically trying to find that two equal numbers. those numbers should be generated with rand() function but i cannot think a way to how to make two random numbers equal to each other if I'm using the rand() function. i don't know if i worded this the best way but i hope you get what i mean and if you don't I'm open to explain it with an example.
thanx in advance!
Just create half as many elements and duplicate them. You can actually take consecutive numbers and shuffle them. This way you make sure every number is repeated exactly once:
int main()
{
enum { size = 10 };
int cards[size];
for (int i = 0; i != size / 2; ++i)
{
cards[i] = i;
cards[size/2 + i] = i;
}
// now shuffle the array
}

How Can I Reduce The Time Taken For The Code Execution Below?

Purpose: To store numbers between 1-1000 in a random order.
My Code:
#include<time.h>
int main(){
int arr[1000]={0}, store[1000];
for(int i=0;i<1000;i++){
int no;
while(1){
srand(time(0));
no=rand();
no%=1001;
if(no==0)
continue;
//This ensures Loop will continue till the time a unique random number is generated
if(arr[no-1]!=no){
arr[no-1]=no;
break;
}
}
store[i]=no;
}
For me the code works perfectly fine,however, it took me 58 minutes to execute. Is there a way to speed up the program?
Practical Purpose: I have around 4000 employees and I want to give each one of them a unique random number for an upcoming project.
I tried to execute a code using 1000 to check the efficiency.
Create an array containing 1 to n. Iterate through the list and swap that entry with one that is randomly selected. You will then have a random list containing 1 to n.
From your first sentence the numbers do not have to be random but only need to be in random order.
Therefore you can try a simple approach:
Create an array arr of n elements and initialize with values 1..n
run a loop (counter i) over range 0..n-1
Pick a random number x in range 0..n-i-1
Swap element at index i with index i+x
With this algorithm you don't need to worry about collisions of random numbers.
You swap the numbers and afterwards you decrease the range of candidates.
A number picked once is not available to pick in later steps.
This solution is similar to William's answer. I don't really know if the result has better "randomness" or not.
Try to avoid branches on random numbers. And it will most likely run faster on modern processors.
This because the processor is not able to predict which way to chose on random numbers.
For example
while(1){
srand(time(0));
no=rand();
no%=1001;
if(no==0)
continue;
// ...
}
could be changed to
srand(time(0)); // better outside the loop
while(1) {
no = rand() % 1000 + 1;
// ...
}

Create actual random data in arrays

I have been working on an assignment, where I have to create a given number of arrays and fill them up with random data. The approach I would like to follow is I want the arrays to be filled with data, only a percentage. The problem is that for every array, the random values are in the same position and not spread how I would like.
I have been creating the arrays in this way:
int **array = malloc(DOC * sizeof *array);
for (i = 0; i < DOC; i++)
{
array[i] = malloc(MAXWORDS * sizeof **array);
}
and filling them using :
srand((unsigned) time(&t));
and
for(i = 0; i < DOC; i++){
for(j = 0; j < MAXWORDS; j++){
array[i][rand() %percentage]=rand() %VALUE;
}
}
Where
int percentage = rand() %MAXWORDS/10;
MAXWORDS defines the lenght of the array
DOC the number of arrays
VALUE is the max random value
As you can see the random values are all behaving identically.
I know that this has to do with the way that srand depends on the time to generate the numbers, and the execution of the program is really fast, so the similar data are because of the "similar" time. So what I am asking is for either a different day to generate random values or some trick I could do to fill the arrays differently.
With "rand() % percentage" you are only picking elements within the first 10% of each array. Instead, you probably want something like this:
for (i = 0; i < DOC; ++i){
for (j = 0; j < MAXWORDS; ++j) {
if (rand() % 100 <= 10) {
array[i][j] = rand() % VALUE;
}
}
}
This gives each elements in the array roughly a 10% chance of being initialized, which should result (for large enough arrays) in about 10% of the elements being initialized.
If you want exactly 10% of the array to be initialized, you could instead do something like placing all indices (0...j) into an array, randomizing the array, and picking the first MAXWORDS/10 indices from the randomized array for initialization.
rand() and srand(), especially when used with %, they don't produce random numbers as uniformly distributed as you may think.
Check Mersenne twister algorithm as an alternative pseudorandom number generator.
I think the problem is with how you are choosing the second index: rand() % percentage will always fill towards the front of the arrays.
The standard random number generator in C (srand + rand) tends to be pretty bad at generating numbers that pass statistical tests for randomness. There are more sophisticated random number generators with better properties available as part of the GNU Scientific Library that you may find helpful.

How to compare and replace (int) pointers?

So i have this piece of code:
int* get_lotto_draw() //Returns an array of six random lottery numbers 1-49
{
int min = 1;
int max = 49;
int counter = 0;
srand(time(NULL));
int *arrayPointer = malloc(6 * sizeof(int));
for(counter = 0; counter <= 5; counter++)
{
arrayPointer[counter] = rand()%(max-min)+min;
}
return arrayPointer;
}
This gives me 6 int* but sometimes these int* values can be the same. How can i compare each of them to eachother, so that if they are the same number, it will re-calculate on of the values that are equal ? Thanks for your time.
make a search in the array for same number before storing the number as,
for(counter = 0; counter <= 5; counter++)
{
int x1 = 1;
while(x1)
{
int temp = rand()%(max-min)+min;
for(i = 0; i < counter; i++)
{
if(arrayPointer[i] == temp)
{
break;
}
}
if(i == counter)
{
x1 = 0;
arrayPointer[counter] = temp;
}
}
}
The problem is that random-number generators don't know or care about history (at least, not in the sense that you do--software random number generators use recent results to generate future results). So, your choices are generally to...
Live with the possibility of duplicates. Obviously, that doesn't help you.
Review previous results and discard duplicates by repeating the draw until the value is unique. This has the potential to never end, if your random numbers get stuck in a cycle.
Enumerate the possible values, shuffle them, and pick the values off the list as needed. Obviously, that's not sensible if you have an enormous set of possible values.
In your case, I'd pick the third.
Create an array (int[]) big enough to hold one of every possible value (1-49).
Use a for loop to initialize each array value.
Use another for loop to swap each entry with a random index. If you swap a position with itself, that's fine.
Use the first few (6) elements of the array.
You can combine the second and third steps, if you want, but splitting them seems more readable and less prone to error to me.

Saving randomly generated numbers in C

I'm trying to find the best way to save a set of randomly generated numbers so they can be recalled later in another function. Basically I have one function that generates the numbers and makes sure they have no repeats, but I need another function that will search the list of numbers to see if the user has picked one of those numbers. whenever I call the random number function within my search function, I just get a list of different random numbers.
Basically I'm just trying to figure out the best way to either save this array of numbers so it doesn't give me knew numbers the next time I call the function, or the best way to pass it on to the next function.
here is the random number generator function, in case you wanted to see what I'm trying to pass onto the next function.
int i, j;
/*generates the set of random numbers*/
for(i = 0; i < MAX; i++) {
random = rand() % 101;
/*checks to to make sure there is no repeats*/
for (j = 0; j < i; j++) {
if (lucky[j] == random) {
random = rand() % 101;
}
}
lucky[i] = random;
printf("%3d",random);
}
Create a new array first:
int *lucky = malloc(amount_of_numbers_you_want * sizeof(int));
Then fill it with random numbers as usual, and then return it. For example:
int* generate_random_numbers(int amount)
{
int *lucky = malloc(amount * sizeof(int));
/* Fill lucky[] with 'amount' unique random numbers. */
return lucky;
}
Then, whenever you call that function, save the pointer it returns somewhere. Do not forget to free() that pointer when you no longer need it, or else you will leak the memory it occupies.
Since this looks like homework, I'm not giving you full code, but rather a general methodology of how you deal with this kind of problem by using dynamically allocated arrays.
So, first of all, that does not ensure the random number are always different:
if your list has [0.1,0.24,0.555] and you add a new RNG with 0.24, it repeats, but can generate a 0.1 which is also stored in lucky[] (and is thus repeated, as you don't like). It is not very probable, but possible.
The way you want is to have a while(), and only when the new RNG is checked against all the list, it is added.
Finally, generally the best way to save a list of RNGs is to set the seed of the RNG. Given a seed "a", the list of numbers generated by the seed "a" is always the same. In that case, your function can even be checking for non-repetitive RNGs, because the result will always be the same.
#Nikos has given correct answer.
You can allocate memory for an array in caller function as well and pass that to random number generating function. Whatever you do make sure lucky isn't locally defined array. Moreover, your logic to generate numbers seems to be wrong (without repetition). As pointed out by #Nikos this seems to be a school assignment, I will just point obvious mistakes.
a) you don't take care of case where second time generated number (second call to random if first random matches with already existing list) is being checked with older set of generated values correctly.
b) random generating function gives you random number between 0 to RAND_MAX and RAND_MAX % 101 isn't 0. That means the probability of getting random number generated isn't uniform.

Resources