Is it possible to use one random number to derive a uniform distribution of a set of numbers?

68 Views Asked by At

Please imagine the following scenario:

Imagine I have an indexed list of reservations, each reservation has an ID:

reservations = [1,2,3,4,5]

Imagine I have an indexed list of tables:

tables = [1,2,3,4,5]

Imagine I have a random unsigned integer (assume this unsigned integer is verifiably random, and only gets generated once):

randomUint = 98346139420554933047845823368198375528330957585398133092102047626198817698038

Each reservation number should use the randomUint to correspond to one of the tables. It isn't an option to run a "shuffle" function by iterating through each of the reservations. Reservation 3 might request their table number before reservation 1 requests their table number. Both of these should deterministically use the randomUint to be assigned a table number.

No numbers should repeat, it should distribute in a similar fashion to this: https://youtu.be/YEBfamv-_do?t=308

Is this possible to do?

1

There are 1 best solutions below

3
On

There seem to be some misconceptions behind this question. For one thing, there is no theoretical difference between a single random integer chosen within a suitable large range of integers (say, $0$ to $M^k - 1$) and a list of several random integers chosen within a smaller range ($0$ to $M - 1$). In fact, if you take $X_1, X_2, \ldots, X_k$ each independently and uniformly chosen at random from the set of integers $\{0, 1, 2, \ldots, M-1\},$ then $$ X = X_1 + M X_2 + M^2 X_3 + \cdots + M^{k-1} X_k $$ is an integer randomly chosen with uniform distribution from the set of integers $\{0, 1, 2, \ldots, M^k-1\}.$

You can run this same process in reverse to extract $k$ random integers from a single integer chosen uniformly from $\{0, 1, 2, \ldots, M^k-1\}.$ Usually in practice (such as in a software implementation) I would prefer to just generate the individual numbers, but you can, for example, start with a single number, divide by $M$ with remainder (and use the remainder as $X_1$), and repeat as many times as you need, provided that the initial number is large enough.


Now to the topics raised in the question:

The linked video demonstrates that if you take the first $16$ powers of $3$ modulo $17,$ you will get a list of sixteen numbers in which each of the numbers $1$ through $16$ appears exactly once without repetition, but in a non-consecutive order. In fact, the mapping $x \mapsto 3^x \bmod 17$ applied to the set $\{1, 2, 3, \ldots, 16\}$ is a permutation of that set of numbers.

You could certainly use such a technique to permute a set of $N$ numbers, provided that $N+1$ has primitive roots. For example, this technique does not work if $N=5,$ because then $N+1=6$; the powers of $2$ modulo $6$ are $2$ and $4$; every power of $3$ modulo $6$ is just $3$; every power of $4$ modulo $6$ is just $4$; the poweres of $5$ modulo $6$ are $5$ and $1$; and of course every power of $1$ is just $1.$

But if $N+1$ has primitive roots and you are able to make a list of at least some of them, you can choose a primitive root at random and you will have a permutation. It will be a relatively limited choice of permutation, but it will at least not just be a constant offset from the input number.

It is not as difficult as you seem to think to get a completely random permutation of $N$ numbers for $N$ not too large (or at least a reasonably "completely random" permutation within the limitations of whatever pseudo-random number generator you have access to). It is an algorithm you can run quickly as soon as you have the value of $N$, and does not require you to do anything with anyone's blockchain.

This can be somewhat more difficult if you are required to use a single verifiably random integer, because you have to do division with remainder to get the random numbers the permutation algorithm needs; and rather than dividing by $M$ each time you might be dividing by $N,$ then $N-1,$ then $N-2,$ and so forth. If the single number is smaller than $N!$ you'll need some way to finish the permutation without the last few random numbers; at that point a primitive root trick might work (because you have some liberty to do it when the number of pairings remaining is a number that has primitive roots), or perhaps you could just do a constant offset within the remaining list of unused output numbers because the previous selections will make the offset within the original list of numbers non-uniform. (That is, instead of just moving ahead $3$ places, for example, you have to move ahead $3$ places plus whatever number of places have already been "used" while you look for the $3$ "unused" places).

In any case, you should be able to translate a large random integer into a shuffled list of $N$ numbers which tells you which number reservation gets assigned to which table, even before the first reservation is claimed.

This will not work if you do not know $N$ at the start (how many reservations to plan for), or if when you receive a reservation you do not know which position in the original list of $N$ reservations it occupied (and it is too expensive to find out), or if given a position in the list of $N$ tables you do not know which table is in that position in the list (and it is too expensive to find out).

But if any of those conditions are true, the constant-offset scheme won't work either, because either you don't know where to start counting the offset from, or after counting the offset you don't know what table you have reached, or you don't know when the offset should "wrap around" to the first table. So if your initial idea was feasible at all, this one should be too.