I’m trying to figure out how to loop through a list and solve every possible combination of numbers that add up to a predetermined value without repeating any numbers in the combination more than how ever many times they appear on the list.
Here’s the code I tried:
import itertools
magicnumber = float(input("Enter desired quantity : "))
lst = [2.7, 9.9, 5.4, 9.0, 5.4, 8.1, 6.3, 4.5, 5.4]
for L in range(0, len(lst)+1):
for subset in itertools.combinations(lst, L):
b = sum(float(i) for i in subset)
if b == magicnumber:
print(subset)
I tried solving all combinations that add up to 18.9 in the list, but can’t figure out how to not have the numbers repeat when adding more than they appear on the list.
I want it to return all combinations like below that add up to 18.9 using only the numbers in the list once, and more than once only how ever many times they repeat.
The result I want to get is:
(9.9, 9.0)
(5.4, 5.4, 8.1)
(2.7, 6.3, 4.5, 5.4)
What I’m currently getting:
(9.9, 9.0)
(5.4, 9.0, 4.5)
(5.4, 5.4, 8.1)
(5.4, 8.1, 5.4)
(9.0, 5.4, 4.5)
(9.0, 4.5, 5.4)
(5.4, 8.1, 5.4)
(8.1, 6.3, 4.5)
(2.7, 6.3, 4.5, 5.4)
I would get all possible combination as you have stated in your question and then just check if the combination is valid:
import itertools
from collections import Counter
def is_combination_valid(subset, cnt):
cnt_subset = Counter(subset)
if any(cnt[c] < cnt_subset.get(c, float("inf")) for c in subset):
return False
for v in subset:
cnt[v] -= 1
return True
magicnumber = 18.9
lst = [2.7, 9.9, 5.4, 9.0, 5.4, 8.1, 6.3, 4.5, 5.4]
cnt = Counter(lst)
for L in range(0, len(lst) + 1):
for subset in itertools.combinations(lst, L):
b = sum(subset)
if b == magicnumber and is_combination_valid(subset, cnt):
print(subset)
Prints:
(9.9, 9.0)
(5.4, 5.4, 8.1)
(2.7, 6.3, 4.5, 5.4)
With:
magicnumber = 18.9
lst = [8.1, 9.9, 5.4, 9.0, 5.4, 8.1, 6.3, 4.5, 5.4]
It prints:
(9.9, 9.0)
(8.1, 5.4, 5.4)
(8.1, 6.3, 4.5)
Sorting might be of use here.
Why doesn’t your desired result include (5.4, 9.0, 4.5)?
You CAN’T use equality here. With two exceptions, none of the numbers in your list (including 18.9) can be expressed in binary. They will all be approximations, and round-off errors means they would add up. You need to use a “close to” function that checks, for example, that
abs(a-b) < 0.0001
or something similar.So, once you use a number in a subset, you can’t use it again? Is the goal to use as many of the numbers as possible? That’s a much more difficult problem, because it requires backtracking. You will have to remove each set from the master set and continue processing.
Once you deal with the floating-point issue (scaling up everything by 10 would work in this particular case), this is easily solved by recursion. The number of combinations from a list that sum to a given total (let’s call that
NC(L, T)
is the sum of the number of combinations from the rest of the list, ignoring the first one (that’s justNC(L[1:], T)
) plus the number of combinations from the rest of the list, including the first one (which isNC(L[1:], T-L[0])
).Show 4 more comments