Reputation: 287
I have an array of 4 values. For example: [0.1, 0.1, 0.5, 0.3]
(sum of elements = 1)
How to iterate though all possible values with increment 0.1 to get in sum 1.
example:
[1.0, 0.0, 0.0, 0,0]
[0.9, 0.1, 0.0, 0,0]
[0.9, 0.0, 0.1, 0,0]
......
[0.7, 0.2, 0.0, 0,1]
Preferably in python or java. Or just algorithm explanation in pseudocode
Upvotes: 0
Views: 566
Reputation: 4508
Instead of the values, pretend you're placing four subintervals into an interval of length 1. Then the four values are determined precisely by the three endpoints of those subintervals.
from itertools import combinations_with_replacement as cwr
for (one,onetwo,onetwothree) in cwr(range(11),3):
print([one/10,(onetwo-one)/10,(onetwothree-onetwo)/10,(10-onetwothree)/10])
Upvotes: 0
Reputation: 22473
This is basically an integer problem couched as a
floating point problem. It can be solved as a
FP problem, but the inexactness of float
representations
and the inability of Python builtins like range
to
provide floating point ranges makes it more difficult.
So easier to solve it in the neat, exact integer realm
then display the results as floating point values.
It's possible to generate all possible combinations of values, then test whether they sum to the target value. That's what some of the other proposed solutions do. But that's a little brute-force. It's also possible to generate only those vectors/lists that sum to the target value. This solution does so with recursive generators.
def vectors(length, target):
"""
Generate all lists of whole numbers of given
length that add up to the target value.
"""
if length == 1:
yield [target]
else:
for firstval in range(target+1):
for rest in vectors(length-1, target-firstval):
yield [firstval] + rest
TARGET=10
LENGTH=4
for vec in vectors(LENGTH, TARGET):
print [ v / float(TARGET) for v in vec ]
This yields:
[0.0, 0.0, 0.0, 1.0]
[0.0, 0.0, 0.1, 0.9]
[0.0, 0.0, 0.2, 0.8]
...
[0.9, 0.0, 0.0, 0.1]
[0.9, 0.0, 0.1, 0.0]
[0.9, 0.1, 0.0, 0.0]
[1.0, 0.0, 0.0, 0.0]
Upvotes: 1
Reputation: 4772
Try the dollowing list comprehension:
>>> from itertools import product
>>> s = [list(p/10. for p in prd)
for prd in product(range(11), repeat=4) if sum(prd) == 10]
>>> len(s)
286
>>> [0.,1.,0.,0.] in s
True
>>> [.8,.2,.0,.0] in s
True
>>>
It is itertools.product that is needed here.
Upvotes: 0
Reputation: 2077
Have a look at itertools.permutations:
import itertools allPermutations = itertools.permutations([0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]*4, 4) Sum1Permutations = [x for x in allPermutations if sum(x) == 1]
As @HuStmpHrrr points out this is using brute force to solve the problem. The algorithm for generating all the permutations which add to 1.0 is this one:
Sum1Permutations = [] for x in range(10): for y in range(10-x+1): for z in range(10-x-y+1): Sum1Permutations.append([float(x)/10, float(y)/10, float(z)/10, float(10 - x - y - z)/10])
Or, using a list comprehension:
Sum1Permutations = [[float(x)/10,float(y)/10,float(z)/10,float(10-x-y-z)/10] for x in range(10) for y in range(10-x+1) for z in range(10-x-y+1)]
Upvotes: 0