I am new to Python and I am slowly learning via Codewars. I know this is potentially against the rules but I have an efficiency question.
You are given a list of integers
ls = [100, 76, 56, 44, 89, 73, 68, 56, 64, 123, 2333, 144, 50, 132, 123, 34, 89]
You must write a function choose_best_sum(t, k, ls)
such that you find a combination of k integers from ls such that the sum of those k intergers is as close to or equal to t.
My final solution passes the tests but on the more detailed testing fails perhaps because of efficiency. I am trying to understand efficiency more. Here is my code
import itertools
def choose_best_sum(t, k, ls):
if sum(sorted(ls)[:k]) > t or len(ls) < k:
return None
else:
combos = itertools.permutations(ls, k)
return max([[sum(i)] for i in set(combos) if sum(i) <= t])[0]
Could someone highlight where the bottleneck is here (I assume on the permutations call) and how this function could be made faster?
EDIT:
The above solution profiled gave
1806730 function calls in 0.458 seconds
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.457 0.457 <string>:1(<module>)
1 0.000 0.000 0.457 0.457 exercises.py:14(choose_best_sum)
742561 0.174 0.000 0.305 0.000 exercises.py:19(<genexpr>)
321601 0.121 0.000 0.425 0.000 exercises.py:20(<genexpr>)
1 0.000 0.000 0.458 0.458 {built-in method builtins.exec}
1 0.000 0.000 0.000 0.000 {built-in method builtins.len}
1 0.032 0.032 0.457 0.457 {built-in method builtins.max}
1 0.000 0.000 0.000 0.000 {built-in method builtins.sorted}
742561 0.131 0.000 0.131 0.000 {built-in method builtins.sum}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
using the assistance I got my final solution was:
def choose_best_sum(t, k, ls):
ls = [i for i in ls if i < t and i < (t - sum(sorted(ls)[:k-1]))]
if sum(sorted(ls)[:k]) > t or len(ls) < k:
return None
else:
return max(s for s in (sum(i) for i in itertools.combinations(ls, k)) if s <= t)
Ordered by: standard name
7090 function calls in 0.002 seconds
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.003 0.003 <string>:1(<module>)
2681 0.001 0.000 0.003 0.000 exercises.py:10(<genexpr>)
1 0.000 0.000 0.003 0.003 exercises.py:5(choose_best_sum)
1 0.000 0.000 0.000 0.000 exercises.py:6(<listcomp>)
1 0.000 0.000 0.003 0.003 {built-in method builtins.exec}
1 0.000 0.000 0.000 0.000 {built-in method builtins.len}
1 0.000 0.000 0.003 0.003 {built-in method builtins.max}
17 0.000 0.000 0.000 0.000 {built-in method builtins.sorted}
4385 0.001 0.000 0.001 0.000 {built-in method builtins.sum}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}