Reputation: 233
i'm trying to find a combination for a sum inside a list of integers.
the amount of numbers that contain the sum is limited by a variable, so for example in the list -
[5,2,3,9,1], i would like to find the sum of 10, with only 2 numbers.
so that the program would print out [9,1].
I'm new to python, is there an easy way of doing it?
thank you.
Upvotes: 7
Views: 11381
Reputation: 1
a = [5,2,3,9,1]
b = []
for i in range(len(a)):
for j in range(i + 1, len(a)):
if (a[i] + a[j] == 10):
b.append((a[i],a[j]))
print(b)
Upvotes: 0
Reputation: 57
#for unsorted array - complexity O(n)
def twoSum(arr, target):
hash = {}
if len(arr) < 2:
return None
for i in range(len(arr)):
if arr[i] in hash:
return [hash[arr[i]], i]
else:
hash[target - arr[i]] = i
return None
twoSum([3,2,8,6],11)
Upvotes: 0
Reputation: 1
lst = [5,2,3,9,1]
lstLen = len(lst)
pair = 0
for i in range(lstLen):
for j in range(lstLen):
if(j <= i ): continue
if((lst[i] + lst[j]) == 10):
pair +=1
print "[%s, %s]" % (lst[i], lst[j])
print "number of pair = %s" % pair
Upvotes: 0
Reputation: 16493
All so far have been O(N^2) or worse, so here's an O(N) solution:
l = [7, 9, 6, 4, 2]
s = set([l[0]])
sum = 10
for num in l[1:]:
diff = sum - num
if diff in s:
print num, diff
else:
s.add(num)
Since the OP asked, here's a more general look at the solution. We have:
numbers
(list of numbers)sum
(desired sum)n
(number of elements we desire to sum to sum
)The easiest is the following:
def find_sum_tuple(numbers, sum, n):
return [tup for tup in itertools.combinations(numbers, n) if sum(tup) == sum]
However, not the best in terms of asymptotic performance. As I showed above, you should be able to get asymptotic O(|numbers
|^(n
-1)) by being more clever and caching sums of n - 1
size.
Upvotes: 4
Reputation: 37319
Just for code golf purposes, here's the collections.Counter
approach:
import collections
integers_list = [5,2,3,9,1]
integer_counts = collections.Counter(integers_list)
for x in integers_list:
y = 10 - x
if (x != y and integer_counts[y]) or (x == y and integer_counts[y] > 1):
print (x, y) # Or, if building a new list, append instead of print
integer_counts.subtract((x, y))
collections.Counter
was added in 2.7. For earlier versions you'd need to use a defaultdict
instead. It's not much more complex.
I think this is harder to read than the itertools.combinations
version @roippi posted, but it should be significantly faster if the list of integers is large. I usually value human time reading the code over machine time executing it, but which consideration wins will depend on your exact situation.
Unlike the itertools
version, this will not return duplicate pairs unless both elements are duplicated. EG, consider a list of [4, 3, 6, 6]. The itertools
version will generate two different (4, 6) pairs and return them both; this version considers the 4 consumed as soon as it's matched to the first 6 and will return only one. If duplication is desired, a set
instead of a Counter
would work - although the special case for 5 gets more complicated unless you build the set iteratively as show in @lollercoaster's answer.
Upvotes: 2
Reputation: 25954
The brute-force approach using itertools.combinations
:
In [6]: [pair for pair in itertools.combinations(li,2) if sum(pair) == 10]
Out[6]: [(9, 1)]
This gives you all pairs that sum to 10. This is superexponential in run time, so if your inputs are large you will want a more sophisticated algorithm.
Upvotes: 3
Reputation: 3722
ls = [5, 2, 3, 9, 1]
sum = 10
while ls:
num = ls.pop()
diff = sum - num
if diff in ls:
print([num, diff])
Upvotes: 3
Reputation: 82440
from itertools import combinations
l = [5,2,3,9,1]
for var in combinations(l, 2):
if var[0] + var[1] == 10:
print var[0], var[1]
Combinations create all possible combinations of tuples
from an iterable object (an object you can loop over). Let me demonstrate:
>>> [var for var in combinations([1,2,3,4,5], 2)]
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]
>>> [var for var in combinations([1,2,3,4,5], 3)]
[(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 4, 5), (2, 3, 4), (2, 3, 5), (2, 4, 5), (3, 4, 5)]
Upvotes: 10