sumoka - 1 year ago 88
Python Question

# Generate N positive integers within a range adding up to a total in python

I have seen other posts addressing similar problem. I know how to generate N positive integers. I also know how to restrict the sum of randomly generated integers. The only problem is satisfying the condition that none of the N values fall out of the specified range.

e.g.

`generate_ints(n, total, low, high)`
should generate n value array such that each value is between low and high and the sum adds up to the total. Any pointers/ help would be greatly appreciated.

e.g.
`generate_ints(4, 40, 4, 15)`
should generate something like

``````[7,10,13,10]
``````

I don't care if the numbers are repeated, as long as they are not highly skewed. I am using
`np.randon.randint(5,15,n)`
to select the integer.

So far, I have tried the following, but it doesn't work -

``````import numpy as np
import random
from random import uniform as rand

total=50
n=10
low=2
high=15
result=[]
m=0
nobs=1
while nobs <= n:
if m >= (total - low):
last_num= total -new_tot
result.append(last_num)
else:
next_num=np.random.randint(low,high,1)
new_tot = sum(result) + next_num
result.append(next_num)
m=new_tot
nobs +=1

print result
print sum(result)
``````

Thanks again.

``````import numpy as np

def sampler(samples, sum_to , range_list):
assert range_list[0]<range_list[1], "Range should be a list, the first element of which is smaller than the second"
arr = np.random.rand(samples)
sum_arr = sum(arr)

new_arr = np.array([int((item/sum_arr)*sum_to) if (int((item/sum_arr)*sum_to)>range_list[0]and int((item/sum_arr)*sum_to)<range_list[1]) \
else np.random.choice(range(range_list[0],range_list[1]+1)) for item in arr])
difference = sum(new_arr) - sum_to
while difference != 0:
if difference < 0 :
for idx in np.random.choice(range(len(new_arr)),abs(difference)):
if new_arr[idx] != range_list[1] :
new_arr[idx] +=  1

if difference > 0:
for idx in np.random.choice(range(len(new_arr)), abs(difference)):
if new_arr[idx] != 0 and new_arr[idx] != range_list[0] :
new_arr[idx] -= 1
difference = sum(new_arr) - sum_to
return new_arr

new_arr = sampler (2872,30000,[5,15])
print "Generated random array is :"
print new_arr
print "Length of array:", len(new_arr)
print "Max of array: ", max(new_arr)
print "min of array: ", min(new_arr)
print "and it sums up to %d" %sum(new_arr)
``````

result :

``````Generated random array is :
[ 9 10  9 ...,  6 15 11]
Length of array: 2872
Max of array:  15
min of array:  5
and it sums up to 30000
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download