Itertools Combinations will not output sequence larger than 3

63 Views Asked by At

In the below code I can not get the result if the output sequence is larger than 3 values. The below code returns nothing, is there any way to get the below code to return the correct answer of 7175.90, 14259.90, 11625.47, and 3764.81?

import itertools
from decimal import Decimal

# Original list of numbers (including decimals)
numbers = [7175.90, 14259.90, 11625.47, 3764.81, 1995.27, 542.23, 2038.32, 4048.83, 490.40, 1279.00, 3248.90]

# Convert the original numbers to Decimal format
#numbers = [Decimal(num) for num in original_numbers]

target_sum = 36826.08
# Generate all combinations of the numbers
result = [seq for i in range(len(numbers), 0, -1) for seq in itertools.combinations(numbers, i) if sum(seq) == target_sum]

print(result)
4

There are 4 best solutions below

2
Andrej Kesely On BEST ANSWER

Use math.isclose - you're using float arithmetics that is not exact:

import itertools
import math

# Original list of numbers (including decimals)
numbers = [
    7175.90,
    14259.90,
    11625.47,
    3764.81,
    1995.27,
    542.23,
    2038.32,
    4048.83,
    490.40,
    1279.00,
    3248.90,
]

target_sum = 36826.08

# Generate all combinations of the numbers
result = [
    seq
    for i in range(len(numbers), 0, -1)
    for seq in itertools.combinations(numbers, i)
    if math.isclose(sum(seq), target_sum)
]

print(result)

Prints:

[(7175.9, 14259.9, 11625.47, 3764.81)]
0
Talha Tayyab On

When I run I get:

Because of floating math you are getting empty list

Floating point math is broken

for seq in itertools.combinations(numbers, 4):
  print((seq),'-->',sum(seq))

(7175.9, 14259.9, 11625.47, 3764.81) --> 36826.079999999994
(7175.9, 14259.9, 11625.47, 1995.27) --> 35056.53999999999
(7175.9, 14259.9, 11625.47, 542.23) --> 33603.5
(7175.9, 14259.9, 11625.47, 2038.32) --> 35099.59
(7175.9, 14259.9, 11625.47, 4048.83) --> 37110.1
(7175.9, 14259.9, 11625.47, 490.4) --> 33551.67
(7175.9, 14259.9, 11625.47, 1279.0) --> 34340.27
(7175.9, 14259.9, 11625.47, 3248.9) --> 36310.17
(7175.9, 14259.9, 3764.81, 1995.27) --> 27195.88
(7175.9, 14259.9, 3764.81, 542.23) --> 25742.84
(7175.9, 14259.9, 3764.81, 2038.32) --> 27238.93
(7175.9, 14259.9, 3764.81, 4048.83) --> 29249.440000000002
(7175.9, 14259.9, 3764.81, 490.4) --> 25691.010000000002
.....
.....


Check your value with your desired value:

36826.079999999994 == 36826.08

#False 
0
Adnan D On
numbers = [7175.90, 14259.90, 11625.47, 3764.81, 1995.27, 542.23, 2038.32, 4048.83, 490.40, 1279.00, 3248.90]

target_sum = 36826.08

# Generate all combinations of the numbers without repetitions and excluding repeated elements
result = set()

for i in range(1, len(numbers) + 1):
    for seq in itertools.combinations(numbers, i):
        if round(sum(seq), 2) == target_sum and len(seq) == len(set(seq)):
            result.add(seq)

print(result)

Output : {(7175.9, 14259.9, 11625.47, 3764.81)}

Note that I have used float instead of Decimal to store the numbers. This is because Decimal is slower and consumes more memory than float and since there is no decimal digits precision we don't get the desired output. Your code does not provide a mechanism to exclude repeated elements within each combination, which may result in duplicate combinations in the output even on eliminating the use of Decimal. You can finally convert the output from my code to list if that is what's needed.

0
no comment On

You can make Decimal work by reconstructing the original written form:

# Convert the original numbers to Decimal format
numbers = [Decimal(str(num)) for num in numbers]
target_sum = Decimal(str(target_sum))

Attempt This Online!