Posts: 39
Threads: 11
Joined: Nov 2020
Jan172021, 08:23 PM
(This post was last modified: Jan172021, 08:24 PM by quest_.)
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?
Posts: 101
Threads: 0
Joined: Jan 2021
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)
Posts: 39
Threads: 11
Joined: Nov 2020
(Jan172021, 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
Posts: 1,490
Threads: 3
Joined: Mar 2020
Yeah, this is small enough that there's only 11^4, or less than 15000. So bruteforce is fine. You could instead bruteforce 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)}")
Posts: 39
Threads: 11
Joined: Nov 2020
(Jan172021, 09:54 PM)bowlofred Wrote: Yeah, this is small enough that there's only 11^4, or less than 15000. So bruteforce is fine. You could instead bruteforce 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?
Posts: 1,490
Threads: 3
Joined: Mar 2020
Jan172021, 10:28 PM
(This post was last modified: Jan172021, 10:28 PM by bowlofred.)
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
Posts: 39
Threads: 11
Joined: Nov 2020
(Jan172021, 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!!!
Posts: 3,619
Threads: 15
Joined: Feb 2020
Jan182021, 05:18 AM
(This post was last modified: Jan182021, 05:18 AM by deanhystad.)
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(11a):
for c in range(11ab):
four.append([a, b, c, 10abc]) The inner loop executes 286 times to give you the 286 possible number combinations.
buran and Serafim like this post
