How to check for duplicates in random numbers [duplicate] - c

I tried generating 10 unique random numbers in C. I have an array numout[] for 10 numbers but this gets to "segmentation fault" after some time.
Tho code is:
int i,j,numout[10],randnum;
void main()
{
srand(time(NULL));
for(i=0;i<10;i++)
{
numout[i]=generate();
printf("%d",numout[i]);
fflush(stdout);
sleep(1);
printf("\b");
}
}
int generate()
{
randnum=1+(int)(rand()*mul_val/(RAND_MAX+1.0));
for(j=0;j<i;j++)
{
if(randnum==0 || randnum==numout[j])
{
randnum=generate();
}
}
return(randnum);
}

Throw that code away, seriously. You need a shuffling algorithm, not a piece of code that checks older values for duplicates. Doing it your way will end up taking longer and longer as your pool runs out. The advantage of a shuffling algorithm is that it doesn't degrade as the pool becomes smaller.
Here's a piece of code I used in answering a different question. It maintains a list of numbers and, when it returns a random one to you, it removes it from the list and decrements the count for the next random selection.
#include <stdio.h>
#include <stdlib.h>
#define ERR_NO_NUM -1
#define ERR_NO_MEM -2
int myRandom (int size) {
int i, n;
static int numNums = 0;
static int *numArr = NULL;
// Initialize with a specific size.
if (size >= 0) {
if (numArr != NULL)
free (numArr);
if ((numArr = malloc (sizeof(int) * size)) == NULL)
return ERR_NO_MEM;
for (i = 0; i < size; i++)
numArr[i] = i;
numNums = size;
}
// Error if no numbers left in pool.
if (numNums == 0)
return ERR_NO_NUM;
// Get random number from pool and remove it (rnd in this
// case returns a number between 0 and numNums-1 inclusive).
n = rand() % numNums;
i = numArr[n];
numArr[n] = numArr[numNums-1];
numNums--;
if (numNums == 0) {
free (numArr);
numArr = 0;
}
return i;
}
int main (void) {
int i;
srand (time (NULL));
i = myRandom (20);
while (i >= 0) {
printf ("Number = %3d\n", i);
i = myRandom (-1);
}
printf ("Final = %3d\n", i);
return 0;
}
A sample output shows it in action:
Number = 19
Number = 10
Number = 2
Number = 15
Number = 0
Number = 6
Number = 1
Number = 3
Number = 17
Number = 14
Number = 12
Number = 18
Number = 4
Number = 9
Number = 7
Number = 8
Number = 16
Number = 5
Number = 11
Number = 13
Final = -1
Call it with a non-negative pool size and it sets up a new sequence and returns the first random value. Following that, you can call it with -1 and it will get the next random, unique number from the pool. When the pool is exhausted, it will return -1.
The other answer that contained this code has a version that can maintain multiple pools as well if you want to be able to use this function in threaded code.

You will get a segmentation fault when you run out of stack space. Your code is recursive (i.e. generate() calls generate()). So when you run out of unused random numbers, it will call itself forever.
However, I will not recommend a fix for your code, because you really need to write it again from scratch. Follow paxdiablo's example.

If you need a large set of unique random numbers you should consider using LFSR approach. LFSR generates unique random numbers that does not repeat unless the entire pool is exhausted, so a 32-bit LFSR will generate 2^32 - 1 unique random numbers -- It does not generate 0. The coding is straight forward, look it up in google.

The program below stores n unique random numbers i.e, from [1 to n] in an array.
#include<iostream.h>
#include<conio.h>
void main()
{
int i, j, Array[100];
cout<<"Enter value of n : "; //upper limit
cin>>n;
randomize();
int rnd;
Array[1]=rand()%n+1;
for(i=2;i<=n;i++)
{
rnd=rand()%n+1;
for(j=1;j<i;j++)
{
if(rnd==Array[j])
{
i--;
break;
}
}
if(j>=i)
Array[i]=rnd;
}
//for printing from random numbers from 1 to n
for(i=1;i<=n;i++)
cout<<Array[i]<<"\n";
getch();
}

Related

How can I find the largest number in an array that is less than or equal to a random integer?

I am working on an assignment and I'm asked to create an array of fibonacci numbers in a range of 0 to 50,000. Once this array has been initialized I am suppose to create a random number between 2 and 10,000. Then, I'm suppose to compare the members of the fibonacci array with the random number to find the greatest fibonacci number that is less than or equal to the random number.
This is the code that I have so far, it correctly creates the array of fibonacci numbers and the random number. How would I start with comparing the members of the array to the random number?
#include <stdio.h>
#include <string.h>
#include <time.h>
void Get_Fibonacci(int n)
{
int fibArray[25];
int lower = 2, upper = 10000, count = 1;
int i, FibRange = 50000;
int first = 0, second = 1, next = 1;
printf("%d %d", first, second);
//Create fibonacci sequence between 0 and 50,000 and store in array
for (i = 2; (first + second) < FibRange; i++)
{
next = first + second;
fibArray[i] = next;
printf(" %d\n", fibArray[i]);
first = second;
second = next;
}
//Create Random Number between 2 and 10,000
srand(time(0));
int k;
for (k = 0; k < count; k++)
{
n = (rand() % upper - lower + 1) + lower;
}
}
I did a little tweaking to your algorithm. This should do what you are asking.
Basically since the Fibonacci sequence combines of sorted numbers, you can do binary search. Also, in your implementation, your array doesn't have to be of size 25 since you are only holding 23 integers. 0 and 1 are saved in independent variables. In addition, your random number generator was wrong.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_N 10000
#define MIN_N 2
void Get_Fibonacci()
{
int fibArray[25];
int lower = 2, upper = 10000, count = 1, middle = 0,found=0;
int low=0,high=0;
int i, FibRange = 50000,n;
int first = 0, second = 1;
printf("\n\t Fibonacci sequence:\n");
fibArray[0]=0;
fibArray[1]=1;
printf("%d\n%d\n",fibArray[0],fibArray[1]);
/* Creates a fibonacci sequence between 0 and 50,000 and store in an array */
for (i=2; (first+second)<FibRange; i++)
{
fibArray[i]=first+second;
first=second;
second=fibArray[i];
printf("%d\n",fibArray[i]);
}
high=i-1 /* Using the for loop exit condition, as chux suggested */
/* Generates a random number between 2 and 10,000 */
srand(time(0));
n = rand()%(MAX_N+1-MIN_N)+MIN_N;
/* Binary search algorithm */
while (low<=high&&!found)
{
middle=(low+high)/2;
if (n==fibArray[middle])
{
count=fibArray[middle];
found=1; /* To terminate the loop if we have an exact match */
}
else if (n<fibArray[middle])
{
high=middle-1;
}
else
{
low=middle+1;
count=fibArray[middle]; /* Saving the number less than key value */
}
}
printf("\n\tRandom number was: %d\n",n);
printf("\n\tClosest match was: %d\n",count);
return;
}
int main(void)
{
Get_Fibonacci();
return 0;
}
First, need to claify somethings:
1) the for loop for creating a random number is useless since count is always is one
2) n should not be a parameter for the function since you generate a random number in the function
3) the i should start from 0, starting from 2 doesn't make any sense to me. You’re just wasting the first two elements in the array
Largest is the variable that carries the value of the largest element and still smaller than n.
int Largest = fibArray[0];
for(int counter=1; counter<25; counter++){
if(fibArray[counter]>Largest && fibArray[counter]<n)
Largest = fibArray[counter];
}
return Largest;
Lambda expression makes these sort of things significantly easier. I suggest learning about lambda and delegates to help with problems like this in the future

I want to optimize this program

I have recently started to learn c and as a programming exercise, I've written a program that computes and lists out prime numbers from 0 up to a maximum entered by the user. It's a rather short program so I'll post the source code here.
// playground.c
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
int main ()
{
int max;
printf("Please enter the maximum number up to which you would like to see all primes listed: "
); scanf("%i", &max);
printf("All prime numbers in the range 0 to %i:\nPrime number: 2\n", max);
bool isComposite;
int primesSoFar[(max >> 1) + 1];
primesSoFar[0] = 2;
int nextIdx = 1;
for (int i = 2; i <= max; i++)
{
isComposite = false;
for (int k = 2; k <= (int)sqrt(i) + 1; k++)
{
if (k - 2 < nextIdx)
{
if (i % primesSoFar[k - 2] == 0)
{
isComposite = true;
k = primesSoFar[k - 2];
}
}else
{
if (i % k == 0) isComposite = true;
}
}
if (!isComposite)
{
printf("Prime number: %i\n", i);
primesSoFar[nextIdx] = i;
nextIdx++;
}
}
double primeRatio = (double)(nextIdx + 1) / (double)(max);
printf("The ratio of prime numbers to composites in range 0 to %d is %lf", max, primeRatio);
return 0;
}
I have become strangely fascinated with optimizing this program but I've hit a wall. The array primesSoFar is allocated based on a computed maximum size which ideally would be no larger than the number of prime numbers from 0 to max. Even if it were just slightly larger, that would be fine; as long as it's not smaller. Is there a way to compute the size the array needs to be that doesn't depend on first computing the primes up to max?
I've updated the code both applying suggested optimizations and adding internal documentation wherever it seemed helpful.
// can compute all the primes up to 0x3FE977 (4_188_535). Largest prime 4_188_533
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
int main ()
{
int max;
printf("Please enter the maximum number up to which you would like to see all primes listed: "
); scanf("%i", &max);
// The algorithm proper doesn't print 2.
printf("All prime numbers in the range 0 to %i:\nPrime number: 2\n", max);
bool isComposite;
// primesSoFar is a memory hog. It'd be nice to reduce its size in proportion to max. The frequency
// of primes diminishes at higher numerical ranges. A formula for calculating the number of primes for
// a given numerical range would be nice. Sadly, it's not linear.
int PRIMES_MAX_SIZE = (max >> 1) + 1;
int primesSoFar[PRIMES_MAX_SIZE];
primesSoFar[0] = 2;
int nextIdx = 1;
int startConsecCount = 0;
for (int i = 2; i <= max; i++)
{
isComposite = false; // Assume the current number isn't composite.
for (int k = 2; k <= (int)sqrt(i) + 1; k++)
{
if (k - 2 < nextIdx) // Check it against all primes found so far.
{
if (i % primesSoFar[k - 2] == 0)
{
// If i is divisible by a previous prime number, break.
isComposite = true;
break;
}else
{
// Prepare to start counting consecutive integers at the largest prime + 1. if i
// isn't divisible by any of the primes found so far.
startConsecCount = primesSoFar[k - 2] + 1;
}
}else
{
if (startConsecCount != 0) // Begin counting consecutively at the largest prime + 1.
{
k = startConsecCount;
startConsecCount = 0;
}
if (i % k == 0)
{
// If i is divisible by some value of k, break.
isComposite = true;
break;
}
}
}
if (!isComposite)
{
printf("Prime number: %i\n", i);
if (nextIdx < PRIMES_MAX_SIZE)
{
// If the memory allocated for the array is sufficient to store an additional prime, do so.
primesSoFar[nextIdx] = i;
nextIdx++;
}
}
}
// I'm using this to get data with which I can find a way to compute a smaller size for primesSoFar.
double primeRatio = (double)(nextIdx + 1) / (double)(max);
printf("The ratio of prime numbers to composites in range 0 to %d is %lf\n", max, primeRatio);
return 0;
}
edit: primesSoFar should be half the size of the range 0 to max. No doubt that's caused some confusion.
I can give you two main ideas as I have worked on a project discussing this problem.
A prime number bigger than 3 is either 6k-1 or 6k+1, so for example 183 can't be prime because 183=6x30+3, so you don't even have to check it. (Be careful, this condition is necessary but not sufficient, 25 for exemple is 6x4+1 but is not prime)
A number is prime if it can't be divided by any prime number smaller or equal to its root, so it's preferable to take a benefit out of the smaller primes you already found.
Thus, you can start with a primesList containing 2 and 3, and iterate k to test all the 6k-1 and 6k+1 numbers (5, 7, 11, 13, 17, 19, 23, 25...) using the second rule I gave you, by using division on elements in the primesList which are smaller than or equal to the root of the number you are checking, if you found only one element dividing it, you just stop and pass to another element, 'cause this one is not prime, otherwise (if no one can divide it): update the primesList by adding this new prime number.
There is some debugging to be done first.
When I saw that the test was <= my brain said BUG as Arrays are subscripted from 0 .. max - 1.
for (int i = 2; i <= max; i++)
So I went to look at the array.
int primesSoFar[(max >> 1) + 1];
Oh he is adding one to the size so it should be ok.
Wait. Why is that shift in there? (max >> 1) is a divide by two.
I compiled the code and ran it, and MSVC reported a memory error.
I removed the shift, and the memory error report went away. The program worked as expected.
With that out of the way, PiNaKa30 and II Saggio Vecchino have very good advice. The choice of algorithm is going to effect the performance dramatically.
Mat gives very good advice. Read the Wikipedia entry. It is filled with wonderful information.
Picking the correct algorithm is key.
How you represent the data you are checking is a factor. int has a maximum value it can hold.
A performance profiler can tell you lots of useful information about where the Hot Spots are in your program.
Congratulations on your efforts in learning C. You picked a very good learning path.
The source code that follows is basically a rewrite. It's running now as I write this. I entered 0x7FFF_FFFF, the 32-bit signed integer positive maximum. In mere minutes on my Acer aspire laptop running on an AMD ryzen 3 with Linux Mint it's already in the hundreds of millions! The memory usage of the old version was half of max, rendering anything larger than 0x3EF977 impossible on my 4gb of RAM. Now it only uses 370728 bytes of memory for its array data when computing primes from 0 to 2_147_483_647.
/*
A super optimized prime number generator using my own implementation of the sieve of Eratosthenes.
*/
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
int main ()
{
int max;
printf("Please enter the maximum to which you would like to see all primes listed: "
); scanf("%i", &max);
/*
Primes and their multiples will be stored until the next multiple of the prime is larger than max.
That prime and its corresponding multiple will then be replaced with a new prime and its corresponding
multiple.
*/
int PRIMES_MAX_SIZE = (int)sqrt(max) + 1;
int primes[PRIMES_MAX_SIZE];
int multiples[PRIMES_MAX_SIZE];
primes[0] = 2;
multiples[0] = 2;
int nextIdx = 1;
int const NO_DISPOSE_SENTINAL_VALUE = -1;
int nextDispose = NO_DISPOSE_SENTINAL_VALUE;
int startConsecCount = 0;
int updateFactor;
bool isComposite;
printf("All prime numbers in the range 0 to %i:\n\n", max);
// Iterate from i = 2 to i = max and test each i for primality.
for (int i = 2; i <= max; i++)
{
isComposite = false;
/*
Check whether the current i is prime by comparing it with the current multiples of
prime numbers, updating them when they are less than the current i and then proceeding
to check whether any consecutive integers up to sqrt(i) divide the current i evenly.
*/
for (int k = 2; k < (int)sqrt(i) + 1; k++)
{
if (k < nextIdx)
{
// Update the multiple of a prime if it's smaller than the current i.
if (multiples[k] < i)
{
updateFactor = (int)(i / primes[k]);
multiples[k] = updateFactor * primes[k] + primes[k];
// Mark the value for disposal if it's greater than sqrt(max).
if (multiples[k] > (int)sqrt(max)) nextDispose = k;
}
if (i == multiples[k])
{
isComposite = true;
break;
}else
{
startConsecCount = multiples[k] + 1;
}
} else
{
if (startConsecCount != 0)
{
k = startConsecCount;
startConsecCount = 0;
}
if (i % k == 0)
{
isComposite = true;
break;
}
}
}
/*
Print the prime numbers and either insert them at indices occupied by disposed primes or at
the next array index if available.
*/
if (!isComposite)
{
printf("Prime number: %i\n", i);
if (nextDispose != NO_DISPOSE_SENTINAL_VALUE)
{
primes[nextDispose] = i;
// This will trigger the update code before the comparison in the inner loop.
multiples[nextDispose] = 0;
nextDispose = NO_DISPOSE_SENTINAL_VALUE;
}else
{
if (nextIdx < PRIMES_MAX_SIZE)
{
primes[nextIdx] = i;
multiples[nextIdx] = 0;
}
}
}
}
return 0;
}
This thing will do the old 0 to 0x3EF977 in the blink of an eye. The old version couldn't do the 32-bit maximum on my system. It's on 201 million + already. I am super chuffed with the results. Thank you for your advice. I wouldn't have made it this far without help.

How do I record the frequency of numbers inputted by a user using functions in C

Hey there i'm currently developing a lotto type game and one of my requirements is to record the frequency of the numbers inputted by the user and then display them if the users wishes to see them. The program also must be modular hence the functions.
My problem is that i can't seem to figure out how to keep track of the numbers I tried numerous things and this is the closest I've gotten...
void num_free(int *picked_nums)
{
static int elements[MAX] = { 0 };
int i;
for (i = 0; i < MAX; i++)
if (*(picked_nums + i) == i)
{
elements[i]++;
}
for (i = 0; i < MAX; i++)
{
if (elements[i] != 0)
{
printf("\nThe amount of times you chose %d is %d", i, elements[i]);
}
}
printf("\nEnter any key to return to main menu");
getchar();
}
The output of this every time i run it no matter the input is
"The amount of times you chose 11 is 1"
I'm really clueless as to what to do next so any and all help would be appreciated. Thanks in advance!
EDIT: The user can play multiple rounds and thats how the frequency of the numbers can add up.
I think the main problem in your code is here:
if (*(picked_nums + i) == i)
{
elements[i]++;
}
you actually check if the i-th number the user chose equals to i. That means that increment is done only in that case - which is not what you want (if I got you right).
I think you should give up the if statement, and, assuming that the user chooses only non-negative numbers (and that the elements array is properly zeroed at the beginning), do this:
elements[picked_nums[i]]++;
Namely, you increment the array cell matching the chosen number (and the i is only the index you use to iterate the picked_num array).
The problem is how you count and store the numbers:
if (*(picked_nums + i) == i)
{
elements[i]++;
}
Your i is moving and at the same time the element chosen from picked_nums is moving. This loop will not count or store properly.
The provided solution assumes that picked numbers are stored in the numbers array. I assumed that numbers are in 1 to 64 range. You can adjust program to your needs. Test provided:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void num_free(int picked_nums[], int size )
{
static int elements[65] = { 0 }; // numbers can be from 1 to 64 range
int i;
for (int j = 0; j < size; j++)
{
int n = picked_nums[j];
for (i = 1; i < 65; i++) // numbers can be from 1 to 64 range
{
if ( n == i)
{
elements[i] = elements[i]+1;
}
}
}
for (i = 0; i < 65; i++)
{
if (elements[i] != 0)
{
printf("\nThe amount of times you chose %d is %d", i, elements[i]);
}
}
// printf("\nEnter any key to return to main menu");
// getchar();
}
// array of entered numbers:
int numbers[] = { 2, 2, 2, 40, 7, 7, 8, 9, 40 };
int main(void) {
num_free(numbers, 9); // call with sizeof numbers
return 0;
}
Test:
The amount of times you chose 2 is 3
The amount of times you chose 7 is 2
The amount of times you chose 8 is 1
The amount of times you chose 9 is 1
The amount of times you chose 40 is 2

What is wrong with my hash function?

I'm trying to create a hash table. Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define N 19
#define c1 3
#define c2 5
#define m 3000
int efort;
int h_table[N];
int h(int k, int i)
{
return (k + i*c1 + i*i*c2) % N;
}
void init()
{
for (int i = 0; i < N; i++)
h_table[i] = -1;
}
void insert(int k)
{
int position, i;
i = 0;
do
{
position = h(k, i);
printf("\n Position %d \n", position);
if (h_table[position] == -1)
{
h_table[position] = k;
printf("Inserted :elem %d at %d \n", h_table[position], position);
break;
}
else
{
i += 1;
}
} while (i != N);
}
void print(int n)
{
printf("\nTable content: \n");
for (int i = 0; i < n; i++)
{
printf("%d ", h_table[i]);
}
}
void test()
{
int a[100];
int b[100];
init();
memset(b, -1, 100);
srand(time(NULL));
for (int i = 0; i < N; i++)
{
a[i] = rand() % (3000 + 1 - 2000) + 2000;
}
for (int i = 0; i < N ; i++)
{
insert(a[i]);
}
print(N);
}
int main()
{
test();
return 0;
}
Hash ("h") function and "insert" function are took from "Introduction to algorithms" book (Cormen).I don't know what is happening with the h function or insert function. Sometimes it fills completely my array, but sometimes it doesn't. That means it doesn't work good. What am I doing wrong?
In short, you are producing repeating values for position often enough to prevent h_table[] from being populated after only N attempts...
The pseudo-random number generator is not guaranteed to produce a set of unique numbers, nor is your h(...) function guaranteed to produce a mutually exclusive set of position values. It is likely that you are generating the same position enough times that you run out of loops before all 19 positions have been generated. The question how many times must h(...) be called on average before you are likely to get the value of an unused position? should be answered. This may help to direct you to the problem.
As an experiment, I increased the looping indexes from N to 100 in all but the h(...) function (so as not to overrun h_table[] ). And as expected the first 5 positions filled immediately. The next one filled after 3 more tries. The next one 10 tries later, and so on, until by the end of 100 tries, there were still some unwritten positions.
On the next run, all table positions were filled.
2 possible solutions:
1) Modify hash to improve probability of unique values.
2) Increase iterations to populate h_table
A good_hash_function() % N may repeat itself in N re-hashes. A good hash looks nearly random in its output even though it is deterministic. So in N tries it might not loop through all the array elements.
After failing to find a free array element after a number of tries, say N/3 tries, recommend a different approach. Just look for the next free element.

Random Permutation Generation

I am having a hard time understand this code example out of my text book. I hope someone can better explain a part of this code then my book. I am sorry for the lack of comments in this program so I will try my best to be very specific in what I am asking. Ok has the title suggest this program is a "Random Permutation Generation". Where I get confused in the code is in the function called bldPerm()
Function bldPerm():
void bldPerm(int randNos[])
{
int oneRandno;
int haveRand[ARY_SIZE] = { 0 };
for (int i = 0 ; i < ARY_SIZE; i++)
{
do
{
oneRandno = rand() % ARY_SIZE;
} while (haveRand[oneRandno] == 1);
haveRand[oneRandno] = 1;
randNos[i] = oneRandno;
}
return;
}
I don't understand how and why the do while loop while(haveRand[oneRandno]) == 1; checks the array by comparing it to 1. Then what confuses me is that haveRand[oneRandno] = 1; is set to one in that element. Then that element being "1" is set to randNos[i] = oneRandno; and returns other numbers other then 1. The program works out of my book and does print out other numbers then 1 yet I just can't see how it works. I have been trying to warp my head around this what I am sure is a simple thing... yet I don't get it. So my question is can anyone explain what is going on in this function in detail and how it works?
FULL CODE:
#define _CRT_SECURE_NO_WARNINGS
#define ARY_SIZE 20
#include <stdio.h>
#include <stdlib.h>
void bldPerm(int randNos[]);
void printData(int data[], int size, int linesSize);
int main(void)
{
int randNos[ARY_SIZE];
printf("Begin Random Permutation Generation\n");
bldPerm(randNos);
printData(randNos, ARY_SIZE, 10);
return 0;
}
void bldPerm(int randNos[])
{
int oneRandno;
int haveRand[ARY_SIZE] = { 0 };
for (int i = 0 ; i < ARY_SIZE; i++)
{
do
{
oneRandno = rand() % ARY_SIZE;
} while (haveRand[oneRandno] == 1);
haveRand[oneRandno] = 1;
randNos[i] = oneRandno;
}
return;
}
void printData(int data[], int size, int linesSize)
{
int numPrinted = 0;
printf("\n");
for (int i = 0; i < size; i++)
{
numPrinted++;
printf("%2d ", data[i]);
if (numPrinted >= linesSize)
{
printf("\n");
numPrinted = 0;
}
}
printf("\n");
return;
}
We want to fill an array with a random permutation of the numbers 0,...,ARY_SIZE-1. This means these number in a completely random ordering.
void bldPerm(int randNos[]) {
int oneRandno;
We keep an array called haveRand which indicates if the number i has already been chosen for our permutation. If the number is chosen haveRand[i] will be set to 1. At the beginning no number is chosen, so we initialize it with 0.
int haveRand[ARY_SIZE] = { 0 };
For each position in our output array we randomly select one of the numbers which have not been selected yet.
for (int i = 0 ; i < ARY_SIZE; i++)
{
Lets find a number which has not been selected yet.
do
{
To do this we sample any random number and call it oneRandno.
oneRandno = rand() % ARY_SIZE;
We check if it not chosen yet. If this is the case, then haveRand[oneRandno] is 0 and the while look will finish. Otherwise we continue and try a new.
} while (haveRand[oneRandno] == 1);
No we mark the selected number as chosen by setting haveRand[oneRandno] to 1.
haveRand[oneRandno] = 1;
Write the chosen number to the output array.
randNos[i] = oneRandno;
}
}
This algorithm is actually quite bad... For example to fill the last element there is only one candidate left as all other numbers are already selected. But the while loop tries to find this number by random sampling which can take a long time.
I would recommend creating an array with numbers 0 to ARY_SIZE-1 and use the Fisher-Yates algorithm to shuffle them.
I went through the code and wrote some comments with the code, i hope that clears it up.
void bldPerm(int randNos[]) // here you give an array of random numbers that is empty
{
// declare an int to store the randomly generated number
int oneRandno;
// initialize an array to store random numbers of size ARY_SIZE
int haveRand[ARY_SIZE] = { 0 };
// now loop while i is smaller then ARY_SIZE and increment i
for (int i = 0 ; i < ARY_SIZE; i++)
{
// here do generate the random number
do
{
// oneRandno will ALWAYS be between -1 and ARY_SIZE
// or i.o.w. from 0 to ARY_SIZE - 1
oneRandno = rand() % ARY_SIZE;
}
// because the numbers have to be unique, if oneRandno
// was already generated loop again
while (haveRand[oneRandno] == 1);
// Set to 1 because the next iteration oneRandno could have the same value,
// however very unlikely because rand() has a period of at least 2^32 which
// gives you enough room to have it generate a whole lot of numbers before
// it generates the same number again. So basically the while loop will
// never loop and act like a glorified if statement.
// and that the values in randNos should unique, if oneRandno has the
// same value the do while loop will iterate once more
// and generate another oneRandno
haveRand[oneRandno] = 1;
// finally store the uniquely generated number
randNos[i] = oneRandno;
//go to the next iteration
}
return;
}

Resources