import random #lets take kg(for Total) for better understanding Total = random.randint(40, 110) #For example Total=100 kg and this is 100% Total = (a+b+c+d+e)
Each value in Total has own range (in %).
First: find random values (within ranges that is % from Total.).
I tried this (but sum() can be >or< than 100):
a=random.randint(40, 70) b=random.randint(0, 4) c=random.randint(0, 2) d=random.randint(22, 44) e=random.randint(0, 7)
Second:find exact value for a,b,c,d,e (according to the percentage from Total in First part). I tried this:
a=Total*random.randint(40, 70)/100 b=Total*random.randint(0, 4)/100 c=Total*random.randint(0, 2)/100 d=Total*random.randint(22, 44)/100 e=Total*random.randint(0, 7)/100
This code does not work. please help
Advertisement
Answer
I’d start with the smallest ranges first, then pick the last one not randomly but as the difference between the sum of the other 4 and 100. Since random numbers can’t be guaranteed to meet all the constraints, you may need to keep picking until you get a satisfactory answer.
def sum_to_100(range_list): if sum(lo for lo,hi in range_list) > 100 or sum(hi for lo,hi in range_list) < 100: raise ValueError('Solution is impossible within the constraints') ordered_ranges = sorted((lo,hi,i) for i,(lo,hi) in enumerate(range_list)) n = len(range_list) solution = [] while len(solution) != n or sum(solution) != 100: index = len(solution) lo, hi, i = ordered_ranges[index] if index == n - 1: final = 100 - sum(solution) if lo <= final <= hi: solution.append(final) else: # start over solution = [] else: solution.append(random.randint(lo, hi)) # restore the original order solution = [num for i,num in sorted(enumerate(solution), key=lambda x:ordered_ranges[x[0]][2])] return solution >>> sum_to_100([(40, 70), (0, 4), (0, 2), (22, 44), (0, 7)]) [59, 3, 1, 32, 5] >>> sum_to_100([(40, 70), (0, 4), (0, 2), (22, 44), (0, 7)]) [47, 2, 0, 44, 7]