I'm trying to create a list of subsets that add to a particular sum (e.g. 12), but with a limit on the occurrences of some of the terms.
The base set to iterate on is {1,2,3,4,5,6,7,8}. I'm trying to find every subset of those elements that sums to 12, regardless of length of the output, but with the condition that {1,2,3} may only be used twice before the set reduces to {4,5,6,7,8}.
Example valid outputs: 165; 1254; 48; 75 Example invalid output: 1317
Is it possible to use itertools.product() expanded in this way? I figured a form of Cartesian product would be necessary, so I tried to use it with the repeat parameter given a range and bind it with the conditionals that set_B below cannot occur more than twice before the range of acceptable inclusions can only be selected from set_C.
from itertools import product
set_A = {1,2,3,4,5,6,7,8}
set_B = {1,2,3}
set_C = {4,5,6,7,8}
finish = (
subsets for subsets in product(set_A, 1 < repeat < 5) if count(set_B) < 3 and sum(subsets) = 12
else:
subsets for subsets in product(set_C, 1 < repeat < 5) if sum(subsets) = 12
)
print("\n", finish)
I was hoping it would produce a full list of valid outputs as in the question (any subset of set_A that equals 12, but with the limitation that members of set_B occurring fewer than 3 times), but I'm not sure of the syntax for some of the functions, so I just get a syntax error. The syntax error occurs on line 7 (pretty much where I would expect it would). Changing the repeat parameter to a set number still results in "Invalid syntax."
Use powerset from Itertools Recipes and a list comprehension filtered by the "sum of 12" requirement and the "fewer than 3 from set_B" requirement.
For example:
from itertools import chain, combinations
set_A = {1,2,3,4,5,6,7,8}
set_B = {1,2,3}
def powerset(iterable):
"Subsequences of the iterable from shortest to longest."
# powerset([1,2,3]) → () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
finish = [x for x in powerset(set_A) if sum(x) == 12 and set_B - set(x)]
print(*finish, sep='\n')
Output:
(4, 8)
(5, 7)
(1, 3, 8)
(1, 4, 7)
(1, 5, 6)
(2, 3, 7)
(2, 4, 6)
(3, 4, 5)
(1, 2, 4, 5)
Note that a non-empty difference set_B - set(x) means <3 of set_B is in set(x) and is evaluated as true.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With