Generate a random number with no repeating digits?

2019-07-17 19:16发布

I'd like to generate a random number with each digit being in range from 0-9 and not repeating itself. Assume finite length of 4.

  • 1234 qualifies, each composite digit is unique.
  • 1123 does not, 1 is repeated

How can this be done please?

标签: c++ random
3条回答
贪生不怕死
2楼-- · 2019-07-17 19:45

To generate the digits:

std::vector<int> vec = {0,1,2,3,4,5,6,7,8,9}; // or initialize from array if not c++11
std::random_shuffle(vec.begin(), vec.end());
vec.resize(4);

And to join the digits into a single number:

int number = 0;
for (auto i = vec.begin(); i != vec.end(); ++i) {
    number = 10 * number + (*i);
}
查看更多
啃猪蹄的小仙女
3楼-- · 2019-07-17 19:54

If you'd rather avoid needless use of std::vector and the memory allocations it brings, excessive randomisation calls presumably used within random_shuffle, there's a simpler approach if you play with some math.

If you can count how many valid (i.e. acceptable) sequences exist, C, and you can devise a bijective function that maps from this counter to each valid sequence instance then things become trivial. Generate a random integer in the range [0,C), plug that into your function which returns the valid output.

If I understand your example correctly, you want to generate a random 4 digit sequence ABCD (representing an integer in the range [0,9999]) where digits A, B, C and D are different from one another.

There are 5040 such valid sequences: 10 * 9 * 8 * 7.

Given any integer in the range [0, 5039], the following function will return a valid sequence (i.e. one in which each digit is unique), represented as an integer:

int counter2sequence(int u) {
  int m = u/504;
  u %= 504;
  int h = u/56;
  u %= 56;
  int t = u/7;
  u %= 7;

  const int ih = h;
  const int it = t;

  if (ih >= m) ++h;
  if (it >= ih) ++t;
  if (t >= m) ++t;
  if (u >= it) ++u;
  if (u >= ih) ++u;
  if (u >= m) ++u;

  return ((m*10 + h)*10 + t)*10 + u;
}

E.g.

counter2sequence(0) => 0123
counter2sequence(5039) => 9876
查看更多
SAY GOODBYE
4楼-- · 2019-07-17 20:02

I believe you are talking about generating permutations.

Try something like this:

int used[10] = {0};
int n = 0;
int number = 0;

while( n < 10 ) {
    int d = rand() % 10;
    if( used[d] ) continue;
    used[d] = 1;
    number = number * 10 + d;
    n++;
}

Not the most efficient... It simply tracks what digits have been used, and rerolls any time a used digit is encountered.

The above does have the side-effect that zero is technically not used if it's the first number chosen. You could explicitly prevent this, or simply accept that some numbers will be 9 digits long.

查看更多
登录 后发表回答