Python Forum

Full Version: Giving all possible values to four different variables
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have for different values which are a b c d. Their sum should be always 1
And they can take 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 but the sum always should be 1. and they can take same values too.
I want to print all possible combinations for these 4 variables like that:

a, b, c, d = 0.5, 0.2, 0.2, 0.1
a, b, c, d = 1.0, 0.0, 0.0, 0.0
a, b, c, d = 0.5, 0.0, 0.4, 0.1
.
.
.
How can I do that in simplest way?
The most obvious way (and ugliest, I guess):
>>> for a in range(11):
...     for b in range(11):
...         for c in range(11):
...             for d in range(11):
...                 if a+b+c+d == 10:
...                     print(a/10, b/10, c/10, d/10)
(Jan-17-2021, 09:45 PM)Serafim Wrote: [ -> ]The most obvious way (and ugliest, I guess):
>>> for a in range(11):
...     for b in range(11):
...         for c in range(11):
...             for d in range(11):
...                 if a+b+c+d == 10:
...                     print(a/10, b/10, c/10, d/10)

Thank you very much but I really do not want to use 4 for loop Because it is a part of a very long code and 4 for loop will make it code much more longer
Yeah, this is small enough that there's only 11^4, or less than 15000. So brute-force is fine. You could instead brute-force through the first 3, then pick the 4th that matches.

from itertools import product

items = [x/10 for x in range(11)]

matching_sets = (x for x in product(items, repeat=4) if 0.99 < sum(x) < 1.01)
for answer in matching_sets:
    print(f"a, b, c, d = {', '.join(str(x) for x in answer)}")
(Jan-17-2021, 09:54 PM)bowlofred Wrote: [ -> ]Yeah, this is small enough that there's only 11^4, or less than 15000. So brute-force is fine. You could instead brute-force through the first 3, then pick the 4th that matches.

from itertools import product

items = [x/10 for x in range(11)]

matching_sets = (x for x in product(items, repeat=4) if 0.99 < sum(x) < 1.01)
for answer in matching_sets:
    print(f"a, b, c, d = {', '.join(str(x) for x in answer)}")

I now wrote this code:

import itertools
for four in itertools.product([0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9, 1.0], repeat=4): 
    a,b,c,d = four[0],four[1],four[2],four[3]
    if a+b+c+d ==1:
        print (a,b,c,d)
Which one is better/efficient?
Beware floating point math. Many decimals cannot be represented exactly. Either check for approximate solutions, or do your math with integers and then divide by 10 later. Otherwise you will run into problems.

>>> 0.3 + 0.3 + 0.3 + 0.1 == 1.0
False
Workaround 1
>>> 3 + 3 + 3 + 1 == 10
True
Workaround 2
>>> 0.99 < 0.3 + 0.3 + 0.3 + 0.1 < 1.01
True
Workaround 3
>>> decimal.Decimal('0.3') + decimal.Decimal('0.3') + decimal.Decimal('0.3') + decimal.Decimal('0.1') == decimal.Decimal('1.0')
True
(Jan-17-2021, 10:28 PM)bowlofred Wrote: [ -> ]Beware floating point math. Many decimals cannot be represented exactly. Either check for approximate solutions, or do your math with integers and then divide by 10 later. Otherwise you will run into problems.

>>> 0.3 + 0.3 + 0.3 + 0.1 == 1.0
False
Workaround 1
>>> 3 + 3 + 3 + 1 == 10
True
Workaround 2
>>> 0.99 < 0.3 + 0.3 + 0.3 + 0.1 < 1.01
True
Workaround 3
>>> decimal.Decimal('0.3') + decimal.Decimal('0.3') + decimal.Decimal('0.3') + decimal.Decimal('0.1') == decimal.Decimal('1.0')
True

Many thanks, I did not notice that before!!!
Use integer 0 through 10 and convert to float when the values are used.
import itertools
four = []
for a, b, c in itertools.product(range(11), repeat=3):
    if (d := 10 - a - b - c) >= 0:
        four.append([a, b, c, d]) # <- Can convert to float here or when used
This code generates 1331 combinations of which 286 are valid.

If you want to be really efficient you can do this:
for a in range(11):
    for b in range(11-a):
        for c in range(11-a-b):
            four.append([a, b, c, 10-a-b-c])
The inner loop executes 286 times to give you the 286 possible number combinations.