I'm trying to generate 10 unique random numbers between 1 and 10. I keep getting duplicate numbers. Can someone tell me what the problem is? What am I missing or need to fix in my code? Thank you!
students[0].id = rand() % 10 + 1;
for (int i = 1; i < 10; i++)
{
students[i].id = rand() % 10 + 1;
for (int j = 0; j < i; j++)
{
if (students[i].id == students[j].id)
{
students[i].id = rand() % 10 + 1 ;
}
}
}
for (int i = 0; i < 10; i++)
{
printf("%d\n", students[i].id);
}
if (students[i].id == students[j].id)
{
students[i].id = rand() % 10 + 1 ;
}
In this line , you may get duplicate.
if students[i].id & students[j].id = 5 means it will get true. But in this line students[i].id = rand() % 10 + 1 ; ,you may get again 5
Instead of above line, you may use this code.
students[0].id = rand() % 10 + 1;
for (int i = 1; i < 10; i++)
{
students[i].id = rand() % 10 + 1;
for (int j = 0; j < i; j++)
{
if (students[i].id == students[j].id)
{
i--;
break;
}
}
}
The function rand() isn't guaranteed to generate unique random numbers. Moreover, your way of limiting the range (mod 10) is especially bad and is likely to generate many duplicates.
The simplest way to generate your sequence is probably to shuffle an array of 10 values from 1 to 10.
rand() is random in nature, so there is no guarantee to give you unique results.
You need to do something like this - keep track of all the numbers encountered so far and call the rand() till you find unique numbers
Random does not mean "No Duplicates".
After you entered this if clause if (students[i].id == students[j].id) and modified students[i].id, you need to check for duplicates again.
Try This One: replace if with while. I hope you get your answer.
students[0].id = rand() % 10 + 1;
for (int i = 1; i < 10; i++)
{
students[i].id = rand() % 10 + 1;
for (int j = 0; j < i; j++)
{
while (students[i].id == students[j].id)
{
students[i].id = rand() % 10 + 1 ;
}
}
}
for (int i = 0; i < 10; i++)
{
printf("%d\n", students[i].id);
}
I think you want to sample without replacement. You can store the indices in an array, randomly pick up one & simultaneously remove it from the array.
So that when you draw next time, it doesn't repeat.
You need recursion.
public static void main(String[] args)
{
System.out.println(generateRandomNumbers(10, new ArrayList<Integer>()));
}
private static List<Integer> generateRandomNumbers(Integer maxLimit, List<Integer> randomNumberList)
{
for (int i = 0; i < maxLimit; i++)
{
Integer tempRandom = new Random().nextInt(10);
if (randomNumberList.contains(tempRandom))
generateRandomNumbers(1, randomNumberList);
else
randomNumberList.add(tempRandom);
}
return randomNumberList;
}
What happens if RAND_MAX (commonly 32767) isn't evenly divisible by 10? You're likely to get values between 1 and 7 more often than 8 and 0. That's a bias.
I would suggest discarding any values greater than or equal to 32760 (or rather, RAND_MAX - RAND_MAX % 10), and using the division operator to construct your random number:
int x;
do {
x = rand();
} while (x >= RAND_MAX - RAND_MAX % 10);
x /= RAND_MAX / 10;
You'll see a fairly drastic improvements from this; In fact, that seems like your most significant bias. However, the distribution of the values you get still isn't required to be uniform. Use a lookup table to discard any values you've previously selected:
int selected[10] = { 0 };
for (int i = 0; i < 10; i++) {
int x;
do {
x = rand();
} while (selected[x / RAND_MAX / 10] || x >= RAND_MAX - RAND_MAX % 10);
x /= RAND_MAX / 10;
selected[x] = 1;
student[i].id = x;
}
for (int i = 0; i < 10; i++) {
printf("student[%d].id: %d\n", i, students[i].id);
}
Related
I completed a challenge in HackerEarth using C but the solution is only partially accepted. I tried to change the data type also but no success.
Question is:
You are given an array A of size N that contains integers. Here, N is an even number. You are required to perform the following operations:
Divide the array of numbers in two equal halves
Note: Here, two equal parts of a test case are created by dividing the array into two equal parts.
Take the first digit of the numbers that are available in the first half of the array (first 50% of the test case)
Take the last digit of the numbers that are available in the second half of the array (second 50% of the test case)
Generate a number by using the digits that have been selected in the above steps
Your task is to determine whether the newly-generated number is divisible by 11.
My solution is:
#include <stdio.h>
#include <math.h>
int main(){
int N;
scanf("%d",&N);
int A[N];
for(int i = 0;i < N;i++)
scanf("%d",&A[i]);
long int sum = 0;
for(int i = 0;i < N/2;i++){
int digits =(int)log10(A[i]);
int first_digit = (int)(A[i] / pow(10,digits));
sum = (sum*10) + first_digit;
}
for(int i = N/2;i < N;i++){
int last_digit = A[i] % 10;
sum = (sum*10)+last_digit;
}
sum % 11 == 0? printf("OUI"):printf("NON");
return 0;
}
The problem says that N will be upto 100,000.
Dealing with such many digits, the calculation of sum will cause overflow.
You should divide sum by 11 and take modulo after each update of sum.
You shouldn't use floating-point numbers or built-in integer types for this kind of problems, because their precisions wouldn't be enough. An integer number is divisible by 11 if the alternating sum of its decimal digits is divisible by 11. So a simple solution would be:
#include <stdio.h>
#include <string.h>
int main (void)
{
int sum = 0, sign = 1;
int n, i;
scanf("%d", &n);
for (i = 0; i < n; ++i) {
char num[100];
scanf("%s", num);
sum += sign * (num[i < n / 2 ? 0 : strlen(num) - 1] - '0');
sign = -sign;
}
puts(sum % 11 == 0 ? "OUI" : "NON");
return 0;
}
Note: Error checking and input validation is omitted for brevity.
100 pecent accepted hackerearth Divisible problem:
#include<stdio.h>
int main() {
long int N;
scanf("%ld", &N);
long int a[N];
int m = 0, n = 0, i;
for (i = 0; i < N; i++)
scanf("%ld", &a[i]);
for (i = 0; i < N / 2; i++) {
if (a[i] >= 100000)
a[i] = a[i] / 100000;
else if (a[i] >= 10000)
a[i] = a[i] / 10000;
else if (a[i] >= 1000)
a[i] = a[i] / 1000;
else if (a[i] >= 100)
a[i] = a[i] / 100;
else if (a[i] >= 10)
a[i] = a[i] / 10;
else
a[i] = a[i];
if (i % 2 == 0)
m += a[i];
else
n += a[i];
}
for (i = N / 2; i < N; i++) {
if (i % 2 == 0)
m += (a[i] % 10);
else
n += (a[i] % 10);
}
if ((abs(m - n)) == 0 || ((abs(m - n)) % 11) == 0)
printf("OUI");
else
printf("NON");
}
function divisibilty(n, arr) {
return arr[n - 1] % 10 == 0 ? "Yes" : "No";
}
console.log(divisibilty(5, [185, 125, 165, 211, 814])); // No
console.log(divisibilty(2, [98, 70])); // Yes
So I am making an array of 52 ints, I add in random numbers and make sure there all different. If there is a duplicate I would generate a new number so that current index that am at is different. Where am I going wrong?
for(i=0; i < SIZE; i++){
deck[i] = (rand() % 52);
for(c= 0; c <= i; c++ ){
if(deck[c] == deck[i+1]){
deck[i] = (rand() % 52);
}
}
}
You can't try merely once for the random number in your inner for loop. After you generate it, you have to check all the previously generated items again to make sure you didn't generate the same random number as another item. This would do the trick (assuming SIZE = 52):
for(i=0; i < SIZE; i++){
deck[i] = (rand() % SIZE);
for(c= 0; c < i; c++ ){
if(deck[c] == deck[i]){
// Try another number
i--;
break;
}
}
}
That said, it's not a very fast solution (it could potentially never end). It's better to create an array of numbers 0 to 51 and then shuffle them by swapping two elements at a time. I'm not going to write that for you, but it's a standard way of doing it.
Totally the wrong approach. You don't want random numbers; you want precisely the numbers 0 to 51, in random order. To do this, fill the array with the values 0..51, and then shuffle it properly:
for (int i = 0; i < 52; i += 1) deck[i] = i;
for (int i = 52; i > 1; i -= 1) {
int j = rand() % i;
int temp = deck[j];
deck[j] = deck[i-1];
deck[i-1] = temp;
}
I am using the Sieve of Eratosthenes to calculate the first 500 prime numbers. What the program does is evauate n % p where n is the user input and p is between 2 and sqrt(n).
I'm testing my program for the case n = 2297, which is a prime. Why does my program say it's composite?
bool primalityTestSieve(int n){
if(n == 2) return true; //tiny complication due to ceil(sqrt(2))
//Sieve with first MAX
bool arr[MAX - 1];
int i, j, s = ceil(sqrt(n));
for(i = 2; i < MAX; i++){
arr[i - 2] = true; //fill arr[] with true
}
for(i = 2; i < (int) sqrt(MAX); i++){
if(arr[i - 2]){
for(j = i*i; j < MAX; j+= i)
arr[j - 2] = false;
}
}
//Array storing the primes
int primes[MAX];
j = 0; //Counter for the index of the primes
for(i = 0; i < MAX; i++)
if(arr[i]){
primes[j] = i + 2;
j++;
}
//Prime test, first using sieve
for(i = 0; primes[i] <= s; i++)
if(n % primes[i] == 0) return false;
//Naive prime test for larger divisors
for (i = primes[j]; i <= s/2; i++)
if(((n % 2) == 0)||((n % (2*i + 1)) == 0)) return false;
return true;
}
Note that MAX is a parameterised macro and is equal to 500.
Your code uses the sieve to find the primes between 2 and 500. (Not the first 500 primes as you seem to say in your text).
Then you copy those primes into the primes[] array with j as the count of how many items are in the array. So at this point primes[] contains some numbers less than 500 followed by a bunch of junk.
Then you have the code:
for(i = 0; primes[i] <= s; i++)
s would be 48 for n == 2297. This loop will then check for n being divisible by any of the primes up to 48 , which would fail. (This loop should also have i < j as a condition so it does not read into the junk if you enter a large n).
However you then write:
for (i = primes[j]; i <= s/2; i++)
Remmeber that j currently holds the prime count, and the primes are in primes[0] through primes[j-1]. This means primes[j] is a junk value; so you set i to junk causing undefined behaviour.
(I'm not sure what you were actually trying to do in that last loop, it's unclear where you want to start and finish, or why you test n%2 every loop iteration, etc. - if you can describe what you are trying to do there then I'll suggest some code).
int main() //8th task
{
int longNum, shortNum, tempNum[5], i;
printf("Please enter 2 numbers (5 digits and 1 digit, ex: 12345 and 5)\n");
scanf("%d%d", &longNum, &shortNum);
for (i = 4; i >= 0; i--)
{
if (longNum % 10 != shortNum)
{
tempNum[i] = longNum % 10;
longNum /= 10;
}
else tempNum[i] = ; // Delete the digit that == shortNum.
}
for (i = 0; i < 5; i++)
{
printf("%d", tempNum[i]);
}
printf("\n");
return 0;
}
This program check if longNum has shortNum in it and suppose to remove the number (and his array slot) from longNum.
I've tried couple of things to make it work with no success.
I'd like to know what is the best way to do it (im not sure what the 'else' should be).
It is possible to skip all shortNum digits in the parsing loop. One more variable is needed to track number of deleted digits:
int n = 5;
for (i = 4; i >= 0; i--)
{
int tmp = longNum % 10;
longNum /= 10;
if (tmp != shortNum)
tempNum[--n] = tmp;
}
// here n is number of deleted digits
for (i = n; i < 5; i++)
{
printf("%d", tempNum[i]);
}
So, actually elements are not deleted from array. They are not written to that array. It is also possible to reverse elements order, so the first array element will be meaningful. Now if some element is skipped the first element of tempNum contains junk.
you need to skip the value that you don't want, and not insert it at all to the array.
int len = 0;
for (i = 4; i >= 0; i--)
{
if (longNum % 10 != shortNum)
{
tempNum[len] = longNum % 10;
len++;
}
longNum /= 10;
}
for (i = 0; i < len; i++)
{
printf("%d", tempNum[i]);
}
else tempNum[i] = ; this part is very wrong. You have to assing something like else tempNum[i] = 0;. And you can't actually delete anything from these arrays - they are not dynamic. I suggest you read up on dynamic arrays.
What is the easiest way to generate 5 random numbers from 1 to 200 such that
randnum[0] < randnum[1] < randnum[2] < randnum[3] < randnum[4]
My code looks like this but it always overflows at randnum[4]
limit_upper = 10; // generate random number up to 10 for randnum[0]
limit_lower = 0;
srand((time(0));
for (x = 0; x < 5; x++) {
randnum[x] = 1 + limit_lower + (unsigned int) rand() % limit_upper;
limit_lower = limit_lower + randnum[x];
limit_upper = (limit_upper * 2) + (unsigned int) rand() % limit_upper;
}
The random numbers to be generated should not repeat.
Any help?
Thank you.
Generate random numbers from 1 to 200, sort them as you go, discard duplicates, until you have 5.
As azhrei pointed out, you're over complicating things. Generate five random numbers between 0 and 200 while throwing out duplicates and sort when finished. This will work well unless you're planning on expanding your code significantly beyond five numbers or have some crazy performance requirements. You'll thank yourself later for the straight forward readable bug-free code. Also, you will remove any artificial limitations to your randomness.
As the accepted answer sugggests, here is the solution:
#include <stdio.h>
#include <stdlib.h>
void quicksort(int arr[], int left, int right) {
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
};
if (left < j)
quicksort(arr, left, j);
if (i < right)
quicksort(arr, i, right);
}
int main() {
int i;
int x;
int random[5];
srand(time(0));
for (i = 0; i < 5; i++) {
random[i] = 0;
}
for (i = 0; i < 5; i++) {
random[i] = rand() % 201;
for (x = 1; x < i; x++) {
if (random[x] == random[i]) {
i--;
continue;
}
}
}
quicksort(random, 0, 4);
for (i = 0; i < 5; i++) {
printf("random[%0d]: %0d \n", i, random[i]);
}
return 0;
}
Maybe someone will find it useful.
Looking at your last line, limit_upper could become anything up to 267 by the 3rd iteration.
The max increase being limit_upper*2 + limit_upper-1 (about 3*limit_upper).
That you get the same problem every time are you seeding your random generator?
This is a classic problem covered from several angles by Jon Bentley in Programming Perls. I highly recommend this book.