2

I was wondering, how can I generate unique random numbers except from a specific one. For example, if I want to generate numbers in range 1 to 10 except from 3, the output should be something like this:

7 6 1 2 4 9 5 8 10
Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
user2791841
  • 71
  • 1
  • 9
  • I think for random number the output "could" rather than "should". – Marc Sep 18 '13 at 14:39
  • As an aside - unique and random are not compatible. A random choice has the same probability of selecting 8 regardless of the fact that the number 8 was just previously selected. Most of the answers given already will provide duplicates. You want a deck (as in deck of cards) shuffling algorithm. @Joni's answer is the only shuffle I've seen so far. – jim mcnamara Sep 18 '13 at 14:39
  • Fisher-Yates' or Floyd's algorithms suit here. – ChronoTrigger Sep 18 '13 at 14:42
  • possible duplicate of [Unique random numbers in O(1)?](http://stackoverflow.com/questions/196017/unique-random-numbers-in-o1). There are other similar questions where the appropriate answer is "Fisher-Yates" including [this one](http://stackoverflow.com/questions/18795004/random-numbers-which-have-not-been-previously-chosen/18795053#18795053) which was just closed yesterday as a duplicate. – Mark Wilkins Sep 18 '13 at 14:46
  • You are looking to generate a random permutation of the input numbers. – chepner Sep 18 '13 at 14:50
  • @jimmcnamara That's not correct. Conditional probabilities that shift the likelihood of outcomes based on prior/other outcomes are an integral part of probability theory. The "birthday problem" calculations that describe the likelihood of hash collisions work out that way precisely because each new number decreases the available pool of values which can avoid a collision. – pjs Sep 18 '13 at 15:21
  • I have updated my answer. See the code. – haccks Sep 18 '13 at 15:31
  • @pjs - Yes. But a discrete random variable, depending on probability density, has an equal chance of generating any given result. See: [Random variable](http://www.stat.yale.edu/Courses/1997-98/101/ranvar.htm). The OP wanted a shuffling algorithm or a random permutation of a set. We are arguing definitions, which is okay. Comments are not well suited to this. In a sense you are correct, mathematically. But PNRG's in C POSIX-standard libraries are as I described -- like rand() or lrand48(). The answers I saw used rand() and company, and potentially provided duplicates. – jim mcnamara Sep 18 '13 at 17:04
  • @jimmcnamara I agree that OP wants shuffling. I'm disputing your initial two sentences. You can have that the conditional probability of generating an 8 is zero given that an 8 has already occurred. PRNGs are as you described, but random variables are not. For random variables, discrete does not imply equiprobable. That's why people who work in this simulation methodology distinguish between random numbers (which are uniformly distributed) and random variates, which are everything else and are generally derived from RNs – pjs Sep 18 '13 at 17:37

6 Answers6

4

Shuffle the numbers 1 - 10 and remove 3.

It doesn't matter if you remove the 3 before or after shuffling.

Alternatively, shuffle the numbers 1 - 9 and relabel 3 as 10...

For shuffling without bias you can use for example the Fisher-Yates algorithm. http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

Joni
  • 108,737
  • 14
  • 143
  • 193
2

Generate random number in the range 1..9 and add one if the number is greater than or equal to 3.

Marc
  • 2,631
  • 1
  • 12
  • 13
2

Generate a number. Check its value, if the number is 3 generate another one. If it isn't 3 then use it.

EDIT: Thinking before coffee is a terrible plan. If you want to get every number in the range in a random order then I agree with the others talking about shuffling lists. If however you want some random subset of the range I would store a list of forbidden values. Shuffling and only taking the first n numbers would also be suitable if the range isn't very large (e.g. not something like 0<x<INT_MAX).

Every time you generate a number check if the generated number is on the forbidden list and if it is, generate another number. Every time you generate a valid number you add it to the list to ensure generated numbers are unique. The list should also be initialised with your unwanted numbers (3 in the example given).

James Elderfield
  • 2,389
  • 1
  • 34
  • 39
0

This code will generate unique random numbers from minimum to maximum of a given range.

#include<stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

int main()
{

    int max_range, min_range, i = 0, rand_num;

    srand((unsigned)time(NULL));
    printf("Enter your maximum of range: ");
    scanf("%d", &max_range);
    printf("Enter your minimum of range: ");
    scanf("%d", &min_range);
    bool digit_seen[max_range + 1]; // VLAs For C99 only 

    for (int i = min_range; i <= max_range; i++)
        digit_seen[i] = false;  

    for (;;)
    {  
         rand_num = rand() % max_range + min_range;
         if(rand_num !=3)
             if(!digit_seen[rand_num])
             {
                printf("%d ", rand_num);
                digit_seen[rand_num] = true;
                i++;
             }
         if( i == (max_range - 1) )
             exit(0);
    }    
    return 0;
}
haccks
  • 104,019
  • 25
  • 176
  • 264
  • You are generating way too much random numbers here. Imagine 8 of the 9 numbers are 'seen'-- you might have to generate dozens of numbers, just to (randomly!) stumble on the last one. Since you are already generating a list, do this instead: (1) pick a random number out of your list, (2) move the last item of your list to this position, (3) decrease length of the list. Repeat until list is empty. – Jongware Sep 18 '13 at 17:21
  • @Jongware; I do not understand how your logic will work here? o.O – haccks Sep 18 '13 at 19:17
  • Your code will blindly keep on generating already-taken random numbers. You are better off to fill the list first (in this case, excluding the unwanted value) and then pick a random one *out of that list*. Once used, *remove* it from the list so it won't be chosen again. The rest is bookkeeping. – Jongware Sep 18 '13 at 22:48
0

You may try like this:-

unsigned int
randomnumber(unsigned int min, unsigned int max)
{
       double scaled = (double)rand()/RAND_MAX;

       return (max - min +1)*scaled + min;
}

then later you can do this:-

 x = randomnumber(1,10);

if (x==3)
{ x = x+1;}

or

if (x!=3)
{ printf("%d",x)}
Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
0

This is my answer - returns random value in [min, max), except "except".

int myrand(int min, int max, int except) {
   int rc;
   do {
      rc = min + rand() % (max - min); 
   } while(rc == except);
   return rc;
}
olegarch
  • 3,670
  • 1
  • 20
  • 19