Is there an efficient way to generate a random combination of N integers such that—
min, max],
Here is the algorithm from John McClane's PermutationPartitionGenerator, in another answer on this page. It has two phases, namely a setup phase and a sampling phase, and generates n random numbers in [min, max] with the sum sum, where the numbers are listed in random order.
Setup phase: First, a solution table is built using the following formulas (t(y, x) where y is in [0, n] and x is in [0, sum - n * min]):
Here, t(y, x) stores the relative probability that the sum of y numbers (in the appropriate range) will equal x. This probability is relative to all t(y, x) with the same y.
Sampling phase: Here we generate a sample of n numbers. Set s to sum - n * min, then for each position i, starting with n - 1 and working backwards to 0:
v to a random integer in [0, t(i+1, s)).r to min.v.v remains 0 or greater, subtract t(i, s-1) from v, add 1 to r, and subtract 1 from s.i in the sample is set to r.EDIT:
It appears that with trivial changes to the algorithm above, it's possible to have each random number use a separate range rather than use the same range for all of them:
Each random number at positions i ∈ [0, n) has a minimum value min(i) and a maximum value max(i).
Let adjsum = sum - Σmin(i).
Setup phase: First, a solution table is built using the following formulas (t(y, x) where y is in [0, n] and x is in [0, adjsum]):
The sampling phase is then exactly the same as before, except we set s to adjsum (rather than sum - n * min) and set r to min(i) (rather than min).
EDIT:
For John McClane's CombinationPartitionGenerator, the setup and sampling phases are as follows.
Setup phase: First, a solution table is built using the following formulas (t(z, y, x) where z is in [0, n], y is in [0, max - min], and x is in [0, sum - n * min]):
Sampling phase: Here we generate a sample of n numbers. Set s to sum - n * min and mrange to max - min, then for each position i, starting with n - 1 and working backwards to 0:
v to a random integer in [0, t(i+1, mrange, s)).mrange to min(mrange, s)mrange from s.r to min + mrange.i, mrange, s) from v.v remains 0 or greater, add 1 to s, subtract 1 from r and 1 from mrange, then subtract t(i, mrange, s) from v.i in the sample is set to r.