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.
Related
The purpose of the program is to create a random list of 1000 numbers in an array, sort that array, then find the greatest set of numbers within (x, x+50). The program successfully generates and sorts the numbers within the array, but crashes when the (i, j) set finding algorithm starts. The program generates no errors on compiling, and I'm sure the error is simple, but for the life of me I can't find the issue. Thanks in advance you amazing people!
int main( ){
int a, b, temp, i, j, x, y, tempTotal, arrayStartMax;
int finalTotal = 0;
int *info[ARRAY_FULL];
for (i=0; i<ARRAY_FULL; i++){
info[i]=(int*)malloc(sizeof(int));
*info[i]=rand()%1000;
}
for (a = 0; a < ARRAY_FULL; ++a){
for (b = a + 1; b < ARRAY_FULL; ++b){
if (*info[a] > *info[b]){
temp = *info[a];
*info[a] = *info[b];
*info[b] = temp;
}
}
}
for (i=0; i<ARRAY_FULL; i++){
printf("%d\n", *info[i]);
}
for (i = 0; i <= ARRAY_HALF; i++){
x = *info[i];
y = x+ARRAY_HALF;
tempTotal = 0;
for (j = i; j < i+ARRAY_HALF; i++){
if (*info[j] >= x || *info[j] <= y) {
tempTotal++;
}
if (tempTotal > finalTotal) {
arrayStartMax = *info[i];
finalTotal = tempTotal;
}
}
}
printf("Interval should start at %d for maximum numbers in a set.", arrayStartMax);
}
For the purpose of this program I would like to mention that ARRAY_FULL = 100 and ARRAY_HALF = 50.
Your code is throwing segfault because you're walking i out of bounds in this for loop.
for (j = i; j < i+ARRAY_HALF; i++){
if (*info[j] >= x || *info[j] <= y) {
tempTotal++;
}
if (tempTotal > finalTotal) {
arrayStartMax = *info[i];
finalTotal = tempTotal;
}
You set j = i then increment i prior to the comparison. So j will always be less than i.
Limit i in the comparison section of the for loop and it won't segfault.
I don't think the comparison is doing what you want, but you should be able to find your way home from here.
I have spent more 10hr+ on trying to sort the following(hexadecimals) in LSD radix sort, but no avail. There is very little material on this subject on web.
0 4c7f cd80 41fc 782c 8b74 7eb1 9a03 aa01 73f1
I know I have to mask and perform bitwise operations to process each hex digit (4 bits), but have no idea on how and where.
I'm using the code (I understand) from GeeksforGeeks
void rsort(int a[], int n) {
int max = getMax(a, n);
for (int exp = 1; max / exp > 0; exp *= 10) {
ccsort(a, n, exp);
}
}
int getMax(int a[], int n) {
int max = a[0];
int i = 0;
for (i = 0; i < n; i++) {
if (a[i] > max) {
max = a[i];
}
}
return max;
}
void ccsort(int a[], int n, int exp) {
int count[n];
int output[n];
int i = 0;
for (i = 0; i < n; i++) {
count[i] = 0;
output[i] = 0;
}
for (i = 0; i < n; i++) {
++count[(a[i] / exp) % 10];
}
for (i = 1; i <= n; i++) {
count[i] += count[i - 1];
}
for (i = n - 1; i >= 0; i--) {
output[count[(a[i] / exp) % 10] - 1] = a[i];
--count[(a[i] / exp) % 10];
}
for (i = 0; i < n; i++) {
a[i] = output[i];
}
}
I have also checked all of StackOverFlow on this matter, but none of them covers the details.
Your implementation of radix sort is slightly incorrect:
it cannot handle negative numbers
the array count[] in function ccsort() should have a size of 10 instead of n. If n is smaller than 10, the function does not work.
the loop for cumulating counts goes one step too far: for (i = 1; i <= n; i++). Once again the <= operator causes a bug.
you say you sort by hex digits but the code uses decimal digits.
Here is a (slightly) improved version with explanations:
void ccsort(int a[], int n, int exp) {
int count[10] = { 0 };
int output[n];
int i, last;
for (i = 0; i < n; i++) {
// compute the number of entries with any given digit at level exp
++count[(a[i] / exp) % 10];
}
for (i = last = 0; i < 10; i++) {
// update the counts to have the index of the place to dispatch the next
// number with a given digit at level exp
last += count[i];
count[i] = last - count[i];
}
for (i = 0; i < n; i++) {
// dispatch entries at the right index for its digit at level exp
output[count[(a[i] / exp) % 10]++] = a[i];
}
for (i = 0; i < n; i++) {
// copy entries batch to original array
a[i] = output[i];
}
}
int getMax(int a[], int n) {
// find the largest number in the array
int max = a[0];
for (int i = 1; i < n; i++) {
if (a[i] > max) {
max = a[i];
}
}
return max;
}
void rsort(int a[], int n) {
int max = getMax(a, n);
// for all digits required to express the maximum value
for (int exp = 1; max / exp > 0; exp *= 10) {
// sort the array on one digit at a time
ccsort(a, n, exp);
}
}
The above version is quite inefficient because of all the divisions and modulo operations. Performing on hex digits can be done with shifts and masks:
void ccsort16(int a[], int n, int shift) {
int count[16] = { 0 };
int output[n];
int i, last;
for (i = 0; i < n; i++) {
++count[(a[i] >> shift) & 15];
}
for (i = last = 0; i < 16; i++) {
last += count[i];
count[i] = last - count[i];
}
for (i = 0; i < n; i++) {
output[count[(a[i] >> shift) & 15]++] = a[i];
}
for (i = 0; i < n; i++) {
a[i] = output[i];
}
}
void rsort16(int a[], int n) {
int max = a[0];
for (int i = 1; i < n; i++) {
if (a[i] > max) {
max = a[i];
}
}
for (int shift = 0; (max >> shift) > 0; shift += 4) {
ccsort16(a, n, shift);
}
}
It would be approximately twice as fast to sort one byte at a time with a count array of 256 entries. It would also be faster to compute the counts for all digits in one pass, as shown in rcgldr's answer.
Note that this implementation still cannot handle negative numbers.
There's a simpler way to implement a radix sort. After checking for max, find the lowest power of 16 >= max value. This can be done with max >>= 4 in a loop, incrementing x so that when max goes to zero, then 16 to the power x is >= the original max value. For example a max of 0xffff would need 4 radix sort passes, while a max of 0xffffffff would take 8 radix sort passes.
If the range of values is most likely to take the full range available for an integer, there's no need to bother determining max value, just base the radix sort on integer size.
The example code you have shows a radix sort that scans an array backwards due to the way the counts are converted into indices. This can be avoided by using an alternate method to convert counts into indices. Here is an example of a base 256 radix sort for 32 bit unsigned integers. It uses a matrix of counts / indices so that all 4 rows of counts are generated with just one read pass of the array, followed by 4 radix sort passes (so the sorted data ends up back in the original array). std::swap is a C++ function to swap the pointers, for a C program, this can be replaced by swapping the pointers inline. t = a; a = b; b = t, where t is of type uint32_t * (ptr to unsigned 32 bit integer). For a base 16 radix sort, the matrix size would be [8][16].
// a is input array, b is working array
uint32_t * RadixSort(uint32_t * a, uint32_t *b, size_t count)
{
size_t mIndex[4][256] = {0}; // count / index matrix
size_t i,j,m,n;
uint32_t u;
for(i = 0; i < count; i++){ // generate histograms
u = a[i];
for(j = 0; j < 4; j++){
mIndex[j][(size_t)(u & 0xff)]++;
u >>= 8;
}
}
for(j = 0; j < 4; j++){ // convert to indices
m = 0;
for(i = 0; i < 256; i++){
n = mIndex[j][i];
mIndex[j][i] = m;
m += n;
}
}
for(j = 0; j < 4; j++){ // radix sort
for(i = 0; i < count; i++){ // sort by current lsb
u = a[i];
m = (size_t)(u>>(j<<3))&0xff;
b[mIndex[j][m]++] = u;
}
std::swap(a, b); // swap ptrs
}
return(a);
}
void int_radix_sort(void) {
int group; //because extracting 8 bits
int buckets = 1 << 8; //using size 256
int map[buckets];
int mask = buckets - 1;
int i;
int cnt[buckets];
int flag = NULL;
int partition;
int *src, *dst;
for (group = 0; group < 32; group += 8) {
// group = 8, number of bits we want per round, we want 4 rounds
// cnt
for (int i = 0; i < buckets; i++) {
cnt[i] = 0;
}
for (int j = 0; j < n; j++) {
i = (lst[j] >> group) & mask;
cnt[i]++;
tmp[j] = lst[j];
}
//map
map[0] = 0;
for (int i = 1; i < buckets; i++) {
map[i] = map[i - 1] + cnt[i - 1];
}
//move
for (int j = 0; j < n; j++) {
i = (tmp[j] >> group) & mask;
lst[map[i]] = tmp[j];
map[i]++;
}
}
}
After hours of researching I came across the answer. I'm still do not understand what is going on in this code/answer. I cannot get my head wrapped around the concept. Hopefully, someone can explain.
I see your points. I think negative numbers are easy to sort after the list has been sorted with something like loop, flag, and swap. wb unsigned float points? – itproxti Nov 1 '16 at 16:02
As for handling floating points there might be a way, for example 345.768 is the number, it needs to be converted to an integer, i.e. make it 345768, I multiplied 1000 with it. Just like the offset moves the -ve numbers to +ve domain, so will multiplying by 1000, 10000 etc will turn the floats to numbers with their decimal part as all zeros. Then they can be typecasted to int or long. However with large values, the whole reformed number may not be accomodated within the entire int or long range.
The number that is to be multiplied has to be constant, just like the offset so that the relationship among the magnitudes is preserved. Its better to use powers of 2 such as 8 or 16, as then bitshifting operator can be used. However just like the calculation of offset takes some time, so will calculation of the multiplier will take some time. The whole array is to be searched to calculate the least number that when multiplied will turn all the numbers with zeros in decimal parts.
This may not compute fast but still can do the job if required.
So I have this segment of code that was given to me.
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++)
{
if (arr[j] < arr[i])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
I am trying to calculate the number of comparison operations that would occur if the code were to run.
There's the initial comparison all the way up to i=100. so there's 101 comparisons for the outer loop. The inner loop also has 101 loops, but that comparison within will only happen 100 times due to the j=100 will not have that comparison occurring.
I've made a tries but none of been the right answer so far.
I've had 101 x (101+100) = 20301 which is not the right answer.
I've searched for this on google and came up with a question identical to this but was answering how many assignment operations that occur which I was able to answer on my own. Which btw is 25201.
I got 20201.
#include <stdio.h>
int main(void) {
int i, j;
unsigned long count;
count = 0;
for (i = 0; ++count, i < 100; ++i) {
for (j = 0; ++count, j < 100; ++j) {
++count;
}
}
(void) printf("%lu\n", count);
return 0;
}
100 comparisons on the outer loop drive 101 + 100 comparisons on the inner loop. There is one more comparison on the outer loop to detect loop termination, so:
100 * (101 + 100) + 101 = 20201.
Instrumenting the program:
outer_cmps=0;
total_inner_cmps=0;
for (int i = 0; i < 100; i++) {
++outer_cmps;
inner_cmps=0;
for (int j = 0; j < 100; j++)
{
++inner_cmps;
if (arr[j] < arr[i])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
++inner_cmps;
}
++inner_cmps;
tota_inner_cmps += inner_cmps;
}
++outer_cmps;
total_cmps = outer_cmps + total_inner_cmps;
So that would be 100*200+100+1=20101
(100 times i, which runs the j loop 100 times, which performs 1 comparisson if (arr[j] < arr[i]) per loop, and one i loop that fails when i==100and 100 times j loop that fail when j==100)
I am writing a program in c to store 2^100000, and I am using arrays to store the result.
Here is the full code:
#include <stdio.h>
#include <math.h>
int main()
{
int test, n, i, j, x, resul;
int a[200], m, temp;
scanf("%d", &test);
for (i = 0; i < test; i++) {
a[0] = 3; // initializes array with only 1 digit, the digit 1.
m = 1; // initializes digit counter
scanf("%d", &n);
temp = 0; // Initializes carry variable to 0.
for (i = 1; i < n; i++) {
for (j = 0; j < m; j++) {
x = a[j] * 2 + temp; //x contains the digit by digit product
a[j] = x % 10; //Contains the digit to store in position j
temp = x / 10; //Contains the carry value that will be stored on later indexes
}
while (temp > 0) { //while loop that will store the carry value on array.
a[m] = temp % 10;
temp = temp / 10;
m++; // increments digit counter
}
}
for (i = m - 1; i >= 0; i--) //printing answer
printf("%d", a[i]);
}
return 0;
}
Can some one tell me a more efficient way to do so to reduce the time complexity?
2^n in binary is an (n+1)-digit integer with every bit set to 0 except the most significant bit being set to 1. e.g: 32 = 2^5 = 0b100000
Likewise, 2^100000 can be computed by setting the 100001-th bit in a zeroed 100001 bit long integer to 1. O(1) is as time efficient as you can go.
There are several problems with your code:
The array a is defined with a size of only 200 digits. This is much too small for 2^100000 that has 30103 digits. You should increase the array size and check for overflow in the multiplication algorithm.
You initialize a[0] = 3; and comment this as the digit 1. Indeed you should write a[0] = 1;.
The second loop for (i = 1; i < n; i++) should include the desired power number: you should write for (i = 1; i <= n; i++).
You use the same loop variable for the outer loop and the second level ones, causing incorrect behavior.
You do not test the return value of scanf, causing undefined behavior on invalid input.
You do not check for overflow, invoking undefined behavior on large values.
Here is a corrected version:
#include <stdio.h>
int main()
{
int n, i, j, x, m, test, temp;
int a[32000];
if (scanf("%d", &test) != 1)
return 1;
while (test-- > 0) {
if (scanf("%d", &n) != 1)
break;
a[0] = 1; // initializes array with only 1 digit, the number 1.
m = 1; // initializes digit counter
temp = 0; // Initializes carry variable to 0.
for (i = 1; i <= n; i++) {
for (j = 0; j < m; j++) {
x = a[j] * 2 + temp; //x contains the digit by digit product
a[j] = x % 10; //Contains the digit to store in position j
temp = x / 10; //Contains the carry value that will be stored on later indexes
}
// while loop that will store the carry value on array.
if (temp > 0) {
if (m >= (int)(sizeof(a)/sizeof(*a)))
break;
a[m++] = temp;
temp = 0;
}
}
if (temp > 0) {
printf("overflow");
} else {
for (i = m - 1; i >= 0; i--) //printing answer
putchar('0' + a[i]);
}
printf("\n");
}
return 0;
}
Running this code with input 1 and 100000 on my laptop takes about 6,5 seconds. That's indeed quite inefficient. Using a few optimization techniques that do not really change the complexity of this simple iterative algorithm still can yield a dramatic performance boost, possibly 100 times faster.
Here are some ideas:
store 9 digits per int in the array instead of just 1.
multiply by 2^29 in each iteration instead of just 2, using long long to compute the intermediary result. Initialize the first step to 1 << (n % 29) to account for n not being a multiple of 29. 2^29 is the largest power of 2 less than 10^9.
Here is version that implements these two ideas:
#include <stdio.h>
int main() {
int n, i, j, m, test, temp;
int a[32000];
if (scanf("%d", &test) != 1)
return 1;
while (test-- > 0) {
if (scanf("%d", &n) != 1)
break;
i = n % 29;
n /= 29;
a[0] = 1 << i;
m = 1;
temp = 0;
for (i = 1; i <= n; i++) {
for (j = 0; j < m; j++) {
long long x = a[j] * (1LL << 29) + temp;
a[j] = x % 1000000000;
temp = x / 1000000000;
}
if (temp > 0) {
if (m >= (int)(sizeof(a)/sizeof(*a)))
break;
a[m++] = temp;
temp = 0;
}
}
if (temp > 0) {
printf("overflow");
} else {
printf("%d", a[m - 1]);
for (i = m - 2; i >= 0; i--)
printf("%09d", a[i]);
}
printf("\n");
}
return 0;
}
Running it on the same laptop computes the correct result in only 33ms, that's 200 times faster.
The Time Complexity is the same, but implementation is much more efficient.
Be aware that native C integers are limited, in practice to some power of two related to the word size of your computer (e.g. typically 32 or 64 bits). Read about <stdint.h> and int32_t & int64_t.
Maybe you want some bignums (or bigints), a.k.a. arbitrary precision arithmetic.
The underlying algorithms are very clever (and more efficient than the naive ones you learned in school). So don't try to reinvent them, and use a library like GMPlib
I chose to do these Project Euler problems in C because I was under the impression that C is fast, but that doesn't seem to be the case. Both of the following loops are extremely slow:
int problem_7 () {
int n = 0;
for (int i = 1; i <= 10001; i++) {
for (int j = (i==1)?1:n+1; j > 0; j++) {
int factorCounter = 0;
for (int k = 1; k <= j/2; k++)
factorCounter += (j % k == 0);
if (factorCounter == 1) {
n = j;
break;
}
}
}
return n;
}
long long int problem_10 () {
long long int sum = 0;
for (int i = 2; i < 2000000; i++) {
int factorCount = 0;
for (int j = 1; j <= i/2; j++) {
factorCount += (i % j == 0);
sum += i*(j == i/2 && factorCount == 1);
}
}
return sum;
}
Is there any way I can make these loops run faster? They do what they're supposed to do, but they each take like 5 minutes to execute.
With branch prediction using boolean numeric values is not as needed:
Looking at problem7 for example, this can be sped up by using if statements:
int n = 0;
for (int i = 1; i <= 10001; i++) {
for (int j = (i==1)?1:n+1; j > 0; j++) {
int factorCounter = 0;
for (int k = 1; k <= j/2; k++)
{
if (j%k==0) // code is changed HERE
{
factorCounter ++;
if (factorCounter > 1)
{
break;
}
} // code change ends here
}
if (factorCounter == 1) {
n = j;
break;
}
}
This completes in 0.88secs as opposed to the original's 9.5secs -- over 10 times faster from that one change
Explanation of optimization and rational for equivalence:
The change made was from the original line:
factorCounter += (j % k == 0);
First change that to its equivalent:
if (j%k==0)
{
factorCounter ++;
}
Notice how factorCounter can only increment, and after the loop any value over 1 is discarded because (factorCounter == 1) will be false, so once it is greater than 1, there is no reason to continue the loop. Also notice that the value of factorCounter can only be changed when (j%k==0) so the test for factorCounter > 1 should occur inside the if check, the code is now:
if (j%k==0)
{
factorCounter ++;
if (factorCounter > 1)
{
break; // We stop the loop much earlier HERE
}
}
And exiting the loop early is what gives the performance gain
I guess I'll make this an answer. Your program is slow because your loops are poorly designed and poorly nested. I'm not going to do a complexity analysis, but you're somewhere in the range of O(N^x) where x > 4 (from what I can tell).
It's just bad programming and it has little to do with loop optimization. You need to use something like the Sieve of Eratosthenes to solve Euler 7. I won't give you the solution here, as with the Wiki article it's fairly trivial to solve.
C is fast. Higher level languages can be fast as well. But even the best compiler can't optimize out the extra operations you're having it do! A simple way to reduce number of operations in your problem 7 algorithm would be to break the deepest for loop if factorCounter becomes greater than 1. Sorry to break it to you but: it's not the compiler it's the algorithm!
A more direct approach to the problem executes almost immediately. You don't really need that many optimizations.
#include <iostream>
#include <cmath>
using namespace std;
bool isPrime(int j)
{
for(int fac = 2; fac < sqrt(j)+0.5; ++fac)
if(j%fac == 0)
return false;
return true;
}
int main()
{
int primesFound = 1; // 2 is prime
int possiblePrime = 1;
while(primesFound != 10001)
{
possiblePrime += 2;
if(isPrime(possiblePrime))
++primesFound;
}
cout << possiblePrime << endl;
}