You want to generate a number in [0;10] or [30;40].
[0;10] is 11 number.
[30;40] is 11 number.
So you can generate a number in [0;21] (22 number to 0 from 21)
Now, if your result is in [0;10], it's good, but if your result is in [11;21] you have to add an offset in order to end in [30;40]. How can you "tranform" [11;21] in [30;40] ? By simply adding 19.
Following the discussion with SteveSummit in comment, here an general implementation of the previous algorithm :
#include <stdlib.h>
#include <stdio.h>
int GetRandomInRanges(int *ranges, size_t size)
{
size_t nbCandidates = 0;
size_t randomNumber;
if (!size || size & 1) {
printf("Error : size must be an even number strictly superior to 0, not %d.\n", size);
exit(1);
}
for (size_t i = 0; i < size; i += 2) {
if (ranges[i] > ranges[i + 1]) {
printf("Error : ranges must be sorted : [%d, %d] is not correct.\n", ranges[i], ranges[i + 1]);
exit(1);
}
nbCandidates += ranges[i + 1] - ranges[i] + 1;
}
randomNumber = (double)rand() / RAND_MAX * nbCandidates;
for (size_t i = 0; i < size; i += 2) {
size_t nbNumberInRange = ranges[i + 1] - ranges[i] + 1;
if (randomNumber < nbNumberInRange) {
return (ranges[i] + randomNumber);
}
randomNumber -= nbNumberInRange;
}
return (0); // Just for the compilator to not throw warning
}
int main(void)
{
int ranges[] = {1, 3, 2, 4};
size_t rangesSize = sizeof(ranges)/sizeof(*ranges);
for (size_t i = 0; i < rangesSize; i += 2)
printf("[%d, %d] ", ranges[i], ranges[i + 1]);
printf("\n");
for (size_t i = 0; i < 10; ++i)
printf("get %d\n", GetRandomInRanges(ranges, rangesSize));
return (0);
}
I have to concede you the fact that it take me near 25minutes to do all the code (coding, testing).