Randomly choose two elements from array and swap values in C - c

I'm writing a program where part of the instructions is to randomly choose two different ord[] elements and then swap their contents. I'm firstly having issues even generating a random element from the array, let alone swapping them (I can't even get it to print the random values). What am I doing wrong? I'm sorry if I'm messing everything up completely. Here is what I have so far:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
#define MMAX 5;
#define ORD_SIZE ( sizeof((ord)) / sizeof((ord[0])) )
int randomOne = 0;
int randomTwo = 0;
int ord[MMAX];
srand(time(NULL));
randomOne = ord[rand() % ORD_SIZE];
randomTwo = ord[rand() % ORD_SIZE];
printf("%d", randomOne);
printf("%d", randomTwo);
int tmp = 0;
tmp = randomOne;
randomOne = randomTwo;
randomTwo = tmp;
printf("%d", ord[randomOne]);
printf("%d", ord[randomTwo]);
return 0;}

You have 2 big problems:
You need to generate random indices and swap the elements at those indices, not take 2 random elements of the array:
.
randomOne = rand() % ORD_SIZE;
randomTwo = rand() % ORD_SIZE;
printf("%d", ord[randomOne]);
printf("%d", ord[randomTwo]);
int temporary = ord[randomOne];
ord[randomOne] = ord[randomTwo];
ord[randomTwo] = temporary;
Your array, ord, is not initialized.
Also, take a look at http://blog.codinghorror.com/the-danger-of-naivete/. Your "randomness" may be a bit biased towards certain indices.

Related

Unexpected return value in this C program

I wrote a C program to find the difference in indices of the largest even number and the smallest even number in an array(here 0 is considered as an even number and from the testcases it definitely didn't look like the array should be sorted). It will return a value or No if the array has one element or no even numbers in that array.
#include <math.h>
#include <stdio.h>
int main() {
int n,small,big,a[50],b1,s1,diff;
scanf("%d",&n);
for(int i =0;i<n;i++){
scanf("%d",&a[i]);
}
small = a[0];
big = a[0];
for (int i = 1; i < n; i++)
{
if (a[i] < small && a[i]%2 == 0)
{
small = a[i];
s1 = i;
}
if (a[i] > big && a[i]%2 == 0)
{
big = a[i];
b1 = i;
}
}
diff = b1-s1;
if(diff==0){
printf("NO");
}
else{
printf("%d",diff);
}
return 0;
}
When I give as input
4
120 0 4 7
It doesn't return 1 . It returns 32657.
What logic am I not understanding here? Please help me.
In this code snippet
small = a[0];
big = a[0];
you also need to initialize s1 and b1
s1 = 0;
b1 = 0;
In general your approach is incorrect because a[0] can be an odd number and can be the greatest or smallest number in the array.
So at first you need to find in the array the first even number and if such a number exists (for example at index i) then write
small = a[i];
big = a[i];
s1 = i;
b1 = i;
Pay attention to that you can include the header <stdio.h> in fact in any place in your program because after the first inclusion of the header all other headers will not be actually included. But do not do that because it makes your program very strange.:)
So remove this directive in main
#include <stdio.h>
Also the directive
#include <math.h>
is redundant because neither declaration from the header is used in your program. You may also remove it.

How could I avoid the pc to pick the same number?

If I have an array like this
int numbers[10] = {1,1,3,3,5,5,7,7,8,8};
And I want to pick one randomly
i = numbers[rand()% 10];
How could I avoid the pc to pick the same number more than twice for this example. Because like you can see in the array the same number is repeated 2 times. So I would like, for example, the number 8 to be choose just twice and same for the other numbers.
I know that I could do something like mark an element as "deleted", e.g., by setting it to 0, then if the number chosen has been deleted, you choose again. But I don't know how to do it properly, so If anyone here can help me I would be very grateful.
You can generate the random number so it's equal to the yet unused number of elements and move unused elements to the front of the array.
#define SZ 10
int numbers[SZ] = {1,1,3,3,5,5,7,7,8,8};
for (int i = 0; i < SZ; ++i)
{
// Generate the random number in the range [0 .. UNUSED-ELEMENTS]
// First loop in range [0..9]
// Second loop in range [0..8]
// and so on
int r = rand() % (SZ-i);
int d = numbers[r];
printf("%d ", d);
// Overwrite the used element with an unused element, i.e. last unused,
// so that unused elements are always at the lowest array index
numbers[r] = numbers[SZ-i-1];
}
printf("\n");
Implemented with an array + "swap and pop":
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static int pick_number(int *numbers, int max)
{
int index = rand() % max;
int result = numbers[index];
// Swap
numbers[index] = numbers[max-1];
return result;
}
int main(int argc, char *argv[])
{
srand(time(NULL));
int numbers[10] = {1,1,3,3,5,5,7,7,8,8};
for (int i = 10; i > 0; i--) {
printf("got: %d\n", pick_number(numbers, i));
}
return 0;
}

How can I use the rand() function to generate a different number that hasn't been generated before?

// What I mean by this is shown by my example:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int i;
int a;
for (a = 0;a <10;a ++) {
i = (rand()%10)+1; // generates a number from 1-10
printf("%d\n", i);
}
// I would like for the loop to generate a number that gives a number that was not generated before. For example, an output such as:
1,3,6,2,8,9,4,10,5,7
instead of:
3,9,10,3,7,9,2,7,10,1
In other words, I would like no copies.
You obviously don't just want no copies, but you want every number in a given set exactly once. This is, as commented by Robert, similar to shuffling a deck of cards. You don't have "decks" in C, but you can model one as an array:
int deck[] = {1,1,1,1,1,1,1,1,1,1};
This should represent 10 different "cards" (identified by their index in the array), each available one time. Now, just write code that "draws" cards:
int i = 0; // starting point for searching for the next card to draw
for (int n = 10; n > 0; --n) // how many cards are left
{
int skip = rand() % n; // randomly skip 0 .. n cards
while (1)
{
if (deck[i]) // card still available?
{
if (!skip) break; // none more to skip -> done
--skip; // else one less to skip
}
if (++i > 9) i = 0; // advance index, wrapping around to 0
}
deck[i] = 0; // draw the card
printf("%d\n", i+1); // and print it out
}
of course, seed the PRNG (e.g. srand(time(0))) first, so you don't get the same sequence every time.
The idea shown in the question is to print numbers within a range, without repetition. Here is one way to do that, by putting each value into an array and swapping its elements around.
A variation could be that you don't want to use all the possible numbers, in that case just change PICKED.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ARRLEN 10
#define PICKED 10
int main(void) {
int array[ARRLEN];
srand((unsigned)time(NULL)); // seed the PRNG
for(int i = 0; i < ARRLEN; i++) { // generate the numbers
array[i] = i + 1;
}
for(int i = 0; i < ARRLEN; i++) { // shuffle the array
int index = rand() % ARRLEN;
int temp = array[i];
array[i] = array[index]; // by randomly swapping
array[index] = temp;
}
for(int i = 0; i < PICKED; i++) { // output the numbers
printf("%d ", array[i]);
}
printf("\n");
}
Program output:
9 8 4 5 1 10 7 3 6 2
The library's PRNG is not very random, but for many cases that is not important. If it is, better algorithms are available.

C How to Keep a Random Variable From Repeating the Same Number

So I'm just learning C and I would like to know how you could prevent a variable randomized with the rand() function from repeating the same number. I have a script which simply randomizes and prints a variable in a for loop 4 times. How could I make it so the variable never gets the same number after each time it uses the rand() function?
#include <stdio.h>
#include <stdlib.h>
int randomInt;
int main()
{
srand(time(0));
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4;
printf("%d\n", randomInt);
}
return 0;
}
On most machines, int is 32 bits. So after 232 iterations, you are sure that you'll get some repetition (and probably much before).
If you restrict yourself to much less loops, consider e.g. keeping an array of previously met random numbers (or some hash table, or some binary tree, or some other container).
For a loop repeated only 4 times, keeping an array of (at most 4-1) previously emitted numbers is quite simple, and efficient enough.
Read also about the pigeonhole principle.
A slightly different approach.
int set[] = {0, 1, 2, 3 } ;
srand(time(0));
shuffle(set,4);
using the shuffle algorithm given in this question
https://stackoverflow.com/a/6127606/9288531
I'm guessing that you are getting the same numbers because your are running your program multiple times within the same second. If time(0) hasn't changed, you will have the same seed and the same random numbers generated. Unless your program runs extremely quickly, I imagine using a seed based on microseconds instead of seconds would work:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int randomInt;
int main()
{
struct timeval my_microtimer;
gettimeofday(&t1, NULL);
srand(t1.tv_sec * my_microtimer.tv_usec);
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4;
printf("%d\n", randomInt);
}
return 0;
}
What you could do is keeping track of each number you already generated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int hasMyNumberAlreadyBeenGenerated(int number, int generatedNumbers[], int size){
for(int i = 0; i < size + 1; i++){
//If you already generated the number, it should be present somewhere in your array
if(generatedNumbers[i] == number) return 1;
//If you did not, find the first available space in your array, and put the number you generated into that space
if(generatedNumbers[i] == 0){
generatedNumbers[i] = number;
break; //No need to continue to check the array
}
}
return 0;
}
int main()
{
int randomInt;
int generatedNumbers[4];
//We set "0" in all the array, to be sure that the array doesn't contain unknown datas when we create it
memset(generatedNumbers, 0x0, sizeof(generatedNumbers));
srand(time(0));
for (int i = 0; i < 4; ++i) {
randomInt = rand() % 4 + 1;
//As long as the number you generate has already been generated, generate a new one
while(hasMyNumberAlreadyBeenGenerated(randomInt, generatedNumbers, i) == 1){
randomInt = rand() % 4 + 1;
}
printf("generated : %d\n", randomInt);
}
return 0;
}
The problem with this method is that you can't generate a 0, because if you do you'll endlessly loop.
You can bypass this problem using a dynamic array using malloc() function.
If you want to write clean code you should define how many numbers you want to generate with a #define.
What you seem to be asking is a non-random set of numbers 0 to 3 in a random order. Given that;
int set[] = {0, 1, 2, 3 } ;
int remaining = sizeof(set) / sizeof(*set) ;
while( remaining != 0 )
{
int index = rand() % sizeof(set) / sizeof(*set) ;
if( set[index] > 0 )
{
printf( "%d\n", set[index] ) ;
set[index] = -1 ;
remaining-- ;
}
}
For very large sets, this approach may not be practical - the number of iterations necessary to exhaust the set is non-deterministic.

Need Help software is not exactly performs the required

Hello friends I need your help.
My program is such an array size 1000 where the numbers should be between 0-999. These numbers should be determined randomly (rand loop) and the number must not be repeated. Would be considered the main part, I have to count how many times I used rand().
My idea is that: one loop where it initializes all the 1000 numbers, and if in this loop they check whether the number appears twice, if the number appears twice is set it again until that not appear twice (maybe this is not the best way but ...)
It is my exercise (Here I need your help)-
#include <stdio.h>
#include <stdlib.h>
int main()
{
int const arr_size = 1000;
int i, j, c;
int arr[arr_size];
int loop = 0;
for(i = 0; i<arr_size; i++)
{
arr[i] = rand() % 1000;
loop++;
if (arr[i] == arr[i - 1])
{
arr[i] = rand() % 1000;
loop++;
}
}
printf("%d\n",loop);
}
So if anyone can give me advice on how I can make it work I appreciate your help.
Thanks.
As suggested, shuffling the set will work but other indirect statistical quantities might be of interest, such as the distribution of the loop variable as a function of the array index.
This seemed interesting so I went ahead and plotted the distribution of the loop as a function of the array index, which generally increases as i increases. Indeed, as we get near the end of the array, the chance of getting a new random number that is not already in the set decreases (and hence, the value of the loop variable increases; see the code below).
Specifically, for an array size = 1000, I recorded the non-zero values generated for loop (there were around 500 duplicates) and then made a plot vs the index.
The plot looks like this:
The code below will produce an array with the unique random values, and then calculate the value for loop. The loop values could be stored in another array and then saved for later analysis, but I didn't include that in the code below.
Again, I'm not exactly sure this fits the application, but it does return information that would not necessarily be available from an approach using a shuffle algorithm.
NOTE: some folks expressed concerns about how long this might take but it runs pretty quick, on my 2011 Macbook Pro it took a about a second for an array size of 1000. I didn't do a big-O analysis as a function of the array size, but that would be interesting too.
NOTE 2: its more elegant to use recursion for the numberInSet() function but it seemed best to keep simple.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h> /* If C99 */
const int ARR_SIZE = 1000;
/* Check if the number is in the set up to the given position: */
bool numberInSet(int number, int* theSet, int position);
int main()
{
int* arr = malloc(sizeof(int)*ARR_SIZE);
srand((unsigned int)time(NULL));
/* Intialize array with rand entries, possibly duplicates: */
for(int i = 0; i < ARR_SIZE; i++)
arr[i] = rand() % ARR_SIZE;
/* Scan the array, look for duplicate values, replace if needed: */
for(int i = 0; i < ARR_SIZE; i++) {
int loop = 0;
while ( numberInSet(arr[i], arr, i-1) ) {
arr[i] = rand() % ARR_SIZE;
loop++;
}
/* could save the loop values here, e.g., loopVals[i] = loop; */
}
for(int i = 0; i < ARR_SIZE; i++)
printf("i = %d, %d\n",i,arr[i]);
/* Free the heap memory */
free(arr);
}
bool numberInSet(int number, int* theSet, int position) {
if (position < 0)
return false;
for(int i = 0; i <= position; i++)
if (number == theSet[i])
return true;
return false;
}
To make sure all random number you get in the same program are different, you must seed once the random generator:
srand (time(NULL)); //seed the random generator
//in the loop, rand will use the seeded value
rand() % 1000

Resources