here is an example algorithm for generating numbers whose sum is a specific integer. asking for the summands of an integer is a question with multiple solutions, and in this case a random number generator is used to find one possible solution. the relative distribution of summands is information that is lost in a sum.
to create a function that splits an integer n
into count
integers equal to or greater than min
whose sum is n
,
with the following signature:
integer_summands :: integer:n integer:count integer:min -> (integer ...)
and the following domain:
n = integer count >= 0 n >= (count * min)
count * min
from n
to get the remaining totalcount - 1
random numbers in the range 0 to the remaining totalmin
to each to ensure the minimum value constraintn
may be less likely to occur the higher count
is. in tests with uniform distribution and n = 50
, count = 4
, min = 2
, the maximum possible value 44
occurred only in about 1:30000 applications.integer_summands = (n, count, min) -> t = n - count * min return [] if t < 0 s = [0, t].concat((Math.floor(Math.random() * (t + 1)) for _ in [1...count])) s.sort (a, b) -> a - b s[i + 1] - s[i] + min for i in [0...count]
example usage
integer_summands 50, 4, 2
example results (results will vary because of the use of random)
[12, 2, 28, 8] [20, 5, 12, 13] [14, 16, 16, 4] [11, 21, 7, 11] [2, 13, 23, 12]
integer_summands_unique = (n, count, min) -> s = count * min + (count * (count - 1)) / 2 return [] if n < s t = n - s a = (Math.floor(x * t) for x in ([Math.random() for _ in [1...count-1]].sort())) a = (a[i] - (a[i-1] || 0) for i in [0...a.length]).concat [t - (a[a.length-1] || 0)] a = a.sort () -> Math.random() - 0.5 (min + i + a[i] for i in [0...count]).sort (a, b) -> a - b