best travel python

Question:

https://www.codewars.com/kata/best-travel/train/python

my code times out, what could i have done better?

def choose_best_sum(t, k, ls):
import itertools
values=list(itertools.combinations(ls,k))
distances=[]
for row in values:
    dis=0
    for i in range(k):
        dis+=row[i]
    distances.append(dis)
while len(distances)!=0 and max(distances)>t:
    #print("max:",max(distances),"min:",min(distances))
    distances.pop(distances.index(max(distances)))
if len(distances)==0:
    result="None"
else:
    result=max(distances)
return result

xs = [100, 76, 56, 44, 89, 73, 68, 56, 64, 123, 2333, 144, 50, 132, 123, 34, 89]
choose_best_sum(230, 4, xs)#, 230)
choose_best_sum(430, 5, xs)#, 430)
choose_best_sum(430, 8, xs)#, None)
Asked By: extreme4all

||

Answers:

Writing your own sum is probably slowing you down a lot. using the built in function is almost always going to be faster:

def choose_best_sum(t, k, ls):
    import itertools
    values=list(itertools.combinations(ls,k))
    distances= [sum(row) for row in values]
    #...

When you go to find the largest value smaller than t, you modify the list a bunch before coming up with your result. Python lists are not terribly efficient at getting longer or shorter, so it would be much better to just sort the list and either just iterate until you find the edge of what is greater than t or you could use a binary search.

    #...
    for distance in reversed(sorted(distances)):
        if distance <= t:
            return distance
Answered By: Aaron

Similar to the answer by @Aaron but without sorting the list. Just keep track of the running best.

import itertools

def choose_best_sum(t, k, ls):
    best_sum = 0
    best_set = None
    combinations = itertools.combinations(ls, k)
    for combination in combinations:
        combi_sum = sum(combination)
        if combi_sum <= t and combi_sum > best_sum:
             best_set = combination
             best_sum = combi_sum
    return (best_set, best_sum)

xs = [100, 76, 56, 44, 89, 73, 68, 56, 64, 123, 2333, 144, 50, 132, 123, 34, 89]
xs = [item for item in xs if item < 430]
choose_best_sum(230, 4, xs)#, 230)
choose_best_sum(430, 5, xs)#, 430)
choose_best_sum(430, 8, xs)#, None)

The first thing you can do is just ditch 2333 from xs because that can never be in a combination. I’m not sure why, in addition to creating your own sum, you have while len(distances)!=0 and max(distances)>t: and so much list manipulation (appending and popping). The %timeit result:

%timeit choose_best_sum(430, 8, xs)
5.43 ms ± 72.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Answered By: roganjosh
def choose_best_sum(t, k, ls):
    from itertools import combinations
    ls.sort()
    p=combinations(ls,k)
    l=list(p)
    l=[sum(i) for i in l]
    l.sort()
    if t in l:
        return t
    if len(l)==0:
        return None
    l=l[::-1]
    for i in l:
        if i<t:
            return i
Answered By: LOKESH NAIDU
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.