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.
Related
my development environment : visual studio
Now, I have to create a input file and print random numbers from 1 to 500000 without duplicating in the file. First, I considered that if I use a big size of local array, problems related to heap may happen. So, I tried to declare as a static array. Then, in main function, I put random numbers without overlapping in the array and wrote the numbers in input file accessing array elements. However, runtime errors(the continuous blinking of the cursor in the console window) continue to occur.
The source code is as follows.
#define SIZE 500000
int sort[500000];
int main()
{
FILE* input = NULL;
input = fopen("input.txt", "w");
if (sort != NULL)
{
srand((unsigned)time(NULL));
for (int i = 0; i < SIZE; i++)
{
sort[i] = (rand() % SIZE) + 1;
for (int j = 0; j < i; j++)
{
if (sort[i] == sort[j])
{
i--;
break;
}
}
}
for (int i = 0; i < SIZE; i++)
{
fprintf(input, "%d ", sort[i]);
}
fclose(input);
}
return 0;
}
When I tried to reduce the array size from 1 to 5000, it has been implemented. So, Carefully, I think it's a memory out phenomenon. Finally, I'd appreciate it if you could comment on how to solve this problem.
“First, I considered that if I use a big size of local array, problems related to heap may happen.”
That does not make any sense. Automatic local objects generally come from the stack, not the heap. (Also, “heap” is the wrong word; a heap is a particular kind of data structure, but the malloc family of routines may use other data structures for managing memory. This can be referred to simply as dynamically allocated memory or allocated memory.)
However, runtime errors(the continuous blinking of the cursor in the console window)…
Continuous blinking of the cursor is normal operation, not a run-time error. Perhaps you are trying to say your program continues executing without ever stopping.
#define SIZE 500000<br>
...
sort[i] = (rand() % SIZE) + 1;
The C standard only requires rand to generate numbers from 0 to 32767. Some implementations may provide more. However, if your implementation does not generate numbers up to 499,999, then it will never generate the numbers required to fill the array using this method.
Also, using % to reduce the rand result skews the distribution. For example, if we were reducing modulo 30,000, and rand generated numbers from 0 to 44,999, then rand() % 30000 would generate the numbers from 0 to 14,999 each two times out of every 45,000 and the numbers from 15,000 to 29,999 each one time out of every 45,000.
for (int j = 0; j < i; j++)
So this algorithm attempts to find new numbers by rejecting those that duplicate previous numbers. When working on the last of n numbers, the average number of tries is n, if the selection of random numbers is uniform. When working on the second-to-last number, the average is n/2. When working on the third-to-last, the average is n/3. So the average number of tries for all the numbers is n + n/2 + n/3 + n/4 + n/5 + … 1.
For 5000 elements, this sum is around 45,472.5. For 500,000 elements, it is around 6,849,790. So your program will average around 150 times the number of tries with 500,000 elements than with 5,000. However, each try also takes longer: For the first try, you check against zero prior elements for duplicates. For the second, you check against one prior element. For try n, you check against n−1 elements. So, for the last of 500,000 elements, you check against 499,999 elements, and, on average, you have to repeat this 500,000 times. So the last try takes around 500,000•499,999 = 249,999,500,000 units of work.
Refining this estimate, for each selection i, a successful attempt that gets completely through the loop of checking requires checking against all i−1 prior numbers. An unsuccessful attempt will average going halfway through the prior numbers. So, for selection i, there is one successful check of i−1 numbers and, on average, n/(n+1−i) unsuccessful checks of an average of (i−1)/2 numbers.
For 5,000 numbers, the average number of checks will be around 107,455,347. For 500,000 numbers, the average will be around 1,649,951,055,183. Thus, your program with 500,000 numbers takes more than 15,000 times as long than with 5,000 numbers.
When I tried to reduce the array size from 1 to 5000, it has been implemented.
I think you mean that with an array size of 5,000, the program completes execution in a short amount of time?
So, Carefully, I think it's a memory out phenomenon.
No, there is no memory issue here. Modern general-purpose computer systems easily handle static arrays of 500,000 int.
Finally, I'd appreciate it if you could comment on how to solve this problem.
Use a Fischer-Yates shuffle: Fill the array A with integers from 1 to SIZE. Set a counter, say d to the number of selections completed so far, initially zero. Then pick a random number r from 1 to SIZE-d. Move the number in that position of the array to the front by swapping A[r] with A[d]. Then increment d. Repeat until d reaches SIZE-1.
This will swap a random element of the initial array into A[0], then a random element from those remaining into A[1], then a random element from those remaining into A[2], and so on. (We stop when d reaches SIZE-1 rather than when it reaches SIZE because, once d reaches SIZE-1, there is only one more selection to make, but there is also only one number left, and it is already in the last position in the array.)
Although it is not clearly stated in my excercise, I am supposed to implement Radix sort recursively. I've been working on the task for days, but yet, I only managed to produce garbage, unfortunately. We are required to work with two methods. The sort method receives a certain array with numbers ranging from 0 to 999 and the digit we are looking at. We are supposed to generate a two-dimensional matrix here in order to distribute the numbers inside the array. So, for example, 523 is positioned at the fifth row and 27 is positioned at the 0th row since it is interpreted as 027.
I tried to do this with the help of a switch-case-construct, dividing the numbers inside the array by 100, checking for the remainder and then position the number with respect to the remainder. Then, I somehow tried to build buckets that include only the numbers with the same digit, so for example, 237 and 247 would be thrown in the same bucket in the first "round". I tried to do this by taking the whole row of the "fields"-matrix where we put in the values before.
In the putInBucket-method, I am required to extent the bucket (which I managed to do right, I guess) and then returning it.
I am sorry, I know that the code is total garbage, but maybe there's someone out there who understands what I am up to and can help me a little bit.
I simply don't see how I need to work with the buckets here, I even don't understand why I have to extent them, and I don't see any way to returning it back to the sort-method (which, I think, I am required to do).
Further description:
The whole thing is meant to work as follows: We take an array with integers ranging from 0 to 999. Every number is then sorted by its first digit, as mentioned above. Imagine you have buckets denoted with the numbers ranging from 0 to 9. You start the sorting by putting 523 in bucket 5, 672 in bucket 6 and so on. This is easy when there is only one number (or no number at all) in one of the buckets. But it gets harder (and that's where recursion might come in hand) when you want to put more than one number in one bucket. The mechanism now goes as follows: We put two numbers with the same first digit in one bucket, for example 237 and 245. Now, we want to sort these numbers again by the same algorithm, meaning we call the sort-method (somehow) again with an array that only contains these two numbers and sorting them again, but now my we do by looking at the second digit, so we would compare 3 and 4. We sort every number inside the array like this, and at the end, in order to get a sorted array, we start at the end, meaning at bucket 9, and then just put everything together. If we would be at bucket 2, the algorithm would look into the recursive step and already receive the sorted array [237, 245] and deliver it in order to complete the whole thing.
My own problems:
I don't understand why we need to extent a bucket and I can't figure it out from the description. It is simply stated that we are supposed to do so. I'd imagine that we would to it to copy another element inside it, because if we have the buckets from 0 to 9, putting in two numbers inside the same bucket would just mean that we would overwrite the first value. This might be the reason why we need to return the new, extended bucket, but I am not sure about that. Plus, I don't know how to go further from there. Even if I have an extened bucket now, it's not like I can simply stick it to the old matrix and copy another element into it again.
public static int[] sort(int[] array, int digit) {
if (array.length == 0)
return array;
int[][] fields = new int[10][array.length];
int[] bucket = new int[array.length];
int i = 0;
for (int j = 0; j < array.length; j++) {
switch (array[j] / 100) {
case 0: i = 0; break;
case 1: i = 1; break;
...
}
fields[i][j] = array[j]
bucket[i] = fields[i][j];
}
return bucket;
}
private static int[] putInBucket(int [] bucket, int number) {
int[] bucket_new = int[bucket.length+1];
for (int i = 1; i < bucket_new.length; i++) {
bucket_new[i] = bucket[i-1];
}
return bucket_new;
}
public static void main (String [] argv) {
int[] array = readInts("Please type in the numbers: ");
int digit = 0;
int[] bucket = sort(array, digit);
}
You don't use digit in sort, that's quite suspicious
The switch/case looks like a quite convoluted way to write i = array[j] / 100
I'd recommend to read the wikipedia description of radix sort.
The expression to extract a digit from a base 10 number is (number / Math.pow(10, digit)) % 10.
Note that you can count digits from left to right or right to left, make sure you get this right.
I suppose you first want to sort for digit 0, then for digit 1, then for digit 2. So there should be a recursive call at the end of sort that does this.
Your buckets array needs to be 2-dimensional. You'll need to call it this way: buckets[i] = putInBucket(buckets[i], array[j]). If you handle null in putInBuckets, you don't need to initialize it.
The reason why you need a 2d bucket array and putInBucket (instead of your fixed size field) is that you don't know how many numbers will end up in each bucket
The second phase (reading back from the buckets to the array) is missing before the recursive call
make sure to stop the recursion after 3 digits
Good luck
This small part of my program will generate 2 random values in a loop that will loop infinite amount of times until the condition is met. I generate 2 values then add the two values to into totalNum, that totalNum will then be passed to a pointMatch variable. I need pointMatch to take in only the first total then keep that same exact number throughout the program. After that the next generation of numbers will be generated then are added to a total. I need to check if that total is equal to the previous pointMatch, if not generate new numbers again until the condition is met. I just cant seem to keep pointMatch the same, its always equal to total.
The problem is you ware trying to achieve a goal which is very simple through a very complicated approach, if you want pointMatch to remain the same, then don't generate the second random value through rand() instead, just subtract the first one from pointMatch.
int rollDice() {
/* WRONG: just call this once in the whole program */
srand( time( NULL ));
/* pick a random value */
randValue = 1 + rand() % 6;
secondRandValue = pointMatch - randValue;
return randValue + secondRandValue; //return random total
}
Also, it seems as though all the variables are globals and that is generally a bad sign.
This result is as random as the default random number generator can generate random numbers for both randValue and secondRandValue, if you have any good argument against this approach, please share it.
Im learning basic C on my own and trying to create a poker client. I have an array with cards (called kortArray) and a players hand (called kortHand). My implementation does not shuffle the deck, but add all 52 cards in sequence and then randomly selecting 5 cards from the deck. I've added a flag (called draget) which tells if a card has been picked up befor or not.
Now, when I run the algorithm below, it usually generates five random numbers which makes the player's or computer's hand. But sometimes it generates less then five numbers, even though I've specifically stated to generate five accepted values.
I have two loops, one that runs five times, and the other is nested and runs until it finds a card which hasn't yet been picked. The printf in the middle tells me that this algorithm doesn't always generate five accepted numbers, and when that happens the player's hand contains cards with nonsense-values.
srand((unsigned)(time(0)));
for(i = 0; i < 5; i++) {
int x = rand()%52 + 1;
while (kortArray[x].draget!=1) {
x = rand()%52 + 1;
if (kortArray[x].draget != 1) {
printf("%i\n", x);
kortArray[x].draget = 1;
kortHand[i] = kortArray[x];
}
}
}
The problem still lies in the +1 for the random numbers.
Also, you are first checking in the the first assignment to x if the card is already picked, and than you assign it to an other card.
Why not use something like:
int nr_cards_picked = 0 /* Number of uniquely picked cards in hand */
/* Continue picking cards until 5 unique cards are picked. */
while (nr_cards_picked < 5) {
x = rand() % 52; /* Take a random card */
if (kortArray[x].draget == 0) {
/* Pick this card. */
kortArray[x].draget = 1; /* Card is picked */
kortHand[i] = kortArray[x]; /* Add picked card to hand */
nr_cards_picked++;
}
}
Forgive compiler errors; I don't have a compiler near here.
This case you only have one time a random number call.
Theoretically it might never end but this is not likely.
You have:
int x = rand()%52+1;
while (kortArray[x].draget!=1){
x = rand()%52;
Arrays in C are indexed starting at 0. Your first call to rand() will generate a value starting at 1. Assuming that you declared kortArray[] to hold 52 values, there is about a 2% chance that you will overrun the array.
Your first call to rand() generates values in the range 1..52. Your second call generates 0..51. ONE OF THEM IS WRONG.
A few things of note.
First of all, random number generators are not guaranteed to be random if you do a mod operation on them. Far better is to divide it out into the 52 segments, and choose like that.
Secondly, you would be far better off moving your call to generate a random number inside the while loop to the end, or just not generate one at the beginning of the for loop.
Where your problem is coming into play is that you are sometimes leaving the while loop without actually entering it, because you are randomly generating a number before you enter the loop.
Given all of this, I would do code somewhat as follows:
srand((unsigned)(time(0)));
for(i=0;i<5;i++){
x=-1;
while (kortArray[x].draget!=1){
x = floor(rand()*52);
}
printf("%i\n", x);
kortArray[x].draget=1;
kortHand[i]=kortArray[x];
}
The nested loop is only entered when kortArray[x].draget is not 1. So everytime it is 1, nothing is done and no card is assigned. First make sure you have a unique x and then in all cases update kortHand[i]
I'd suggest a different algorithm:
create a random number between 0 and number of cards in deck
assign the card from that position to the appropriate hand
swap the last card to that postion
decrease the number of cards in the deck by 1.
continue with 1 until the necessary number of cards are dealt.
This way, you get rid of the flag and you can guarantee linear performance. No need to check whether a card has already been dealt or not.
Currently my program allows the user to enter 5 integers which are used to create an average number. This is set to five as after the fifth number is entered the loop is broken.
I am trying to implement a method which will let the user continue to add as many numbers as they like to an array from which i can then use to create an average without a limit on the amount of numbers that can be entered.
I have come across a few problems, firstly i cannot create an array which is dyamic as i have no idea how many numbers the user may wish to enter which means i can't give it a definitive size.
Secondly the way my program currently creates the average is by looping through the elements in the array and adding the consecutively to an integer, from which the the average is made. I cannot specify the limit for the loop to continue running if i cannot determine the array.
Hopefully my example explains this better.
#include <stdio.h>
#include <string.h>
void main()
{
int i = 0;
int arrayNum[5];
int temp = 1;
int anotherTemp = 0;
int answer = 0;
printf("Enter as many numbers as you like, when finished enter a negative number\n");
for(i = 0; i < 5; i++)
{
scanf("%d", &temp);
arrayNum[i] = temp;
anotherTemp = anotherTemp + arrayNum[i];
}
answer = anotherTemp / 5;
printf("Average of %d,%d,%d,%d,%d = %d",arrayNum[0],arrayNum[1],arrayNum[2],arrayNum[3],arrayNum[4],answer);
}
Although this may not be the best way to implement it, it does work when the amount of numbers are specified beforehand.
What would be the best way to get around this and allow the user to enter as many number as necessary?
Edit: Although i needed to use an array I have decided that it is not necessary as the solution is much simpler without being restricted to it.
In terms of code simplicity, you might want to check out the realloc() function; you can allocate an initial array of some size, and if the user enters too many numbers call realloc() to get yourself a bigger array and continue from there.
You don't, however, actually need to keep the numbers as you go along at all, at least if you only care about the average:
int input;
int sum = 0;
int count = 0;
int average;
while (1) {
scanf("%d", &input);
if (input < 0) {
break;
}
sum += input;
count++;
}
average = sum / count;
If you're trying to compute an average, then you don't need to save the numbers. Save yourself the work of worrying about the array. Simply accumulate (add) each number to a single total, count each number, then divide when you're done. Two variables are all that you need.
With this method, you aren't in any risk of overflowing your array, so you can use a while loop... while (temp != -1)
Basically you start with a dynamically allocated array with a fixed size, and then allocate a new array that is bigger (say, twice as big as initial size) and copy the stuff from the old array to the new one whenever you run out of space.
For the second part of the problem, keep a counter of the number of items the user entered and use it when averaging.
Something like this.
Use a dynamic array data structure, like Vector in Java (java.util.Vector).
You can implement such a dynamic array yourself easily:
allocate array of size N
as soon as you need more elements than N, allocate a new bigger array (e.g. with size N+10), copy the content of the old array into the new array and set your working reference to the new array and your array size variable N to the new size (e.g. N+10). Free the old array.