Project Euler 5 in Python - How can I optimize my solution?

后端 未结 20 895
醉梦人生
醉梦人生 2020-11-30 08:00

I\'ve recently been working on Project Euler problems in Python. I am fairly new to Python, and still somewhat new as a programmer.

In any case, I\'ve ran into a sp

相关标签:
20条回答
  • 2020-11-30 08:57

    How about this? The required number is, after all, the LCM of the given numbers.

    def lcm(a,b):
    lcm1 = 0
    if a == b:
        lcm1 = a
    else:
        if a > b:
            greater = a
        else:
            greater = b
        while True:
            if greater % a == 0 and greater % b == 0:
                lcm1 = greater
                break
            greater += 1
    
    return lcm1            
    
    
    import time
    start_time = time.time()
    
    list_numbers = list(range(2,21))
    
    lcm1 = lcm(list_numbers[0],list_numbers[1])
    
    for i in range(2,len(list_numbers)):
        lcm1 = lcm(lcm1,list_numbers[i])
    
    print(lcm1)
    print('%0.5f'%(time.time()-start_time))
    

    This code took a full 45 s to get the answer to the actual question! Hope it helps.

    0 讨论(0)
  • 2020-11-30 08:58

    Taking the advice of Michael Mior and poke, I wrote a solution. I tried to use a few tricks to make it fast.

    Since we need a relatively short list of numbers tested, then we can pre-build the list of numbers rather than repeatedly calling xrange() or range().

    Also, while it would work to just put the numbers [1, 2, 3, ..., 20] in the list, we can think a little bit, and pull numbers out:

    Just take the 1 out. Every integer is evenly divisible by 1.

    If we leave the 20 in, there is no need to leave the 2 in. Any integer evenly divisible by 20 is evenly divisible by 2 (but the reverse might not be true). So we leave the 20 and take out the 2, the 4, and the 5. Leave the 19, as it's prime. Leave the 18, but now we can take out the 3 and the 6. If you repeat this process, you wind up with a much shorter list of numbers to try.

    We start at 20 and step numbers by 20, as Michael Mior suggested. We use a generator expression inside of all(), as poke suggested.

    Instead of a while loop, I used a for loop with xrange(); I think this is slightly faster.

    The result:

    check_list = [11, 13, 14, 16, 17, 18, 19, 20]
    
    def find_solution(step):
        for num in xrange(step, 999999999, step):
            if all(num % n == 0 for n in check_list):
                return num
        return None
    
    if __name__ == '__main__':
        solution = find_solution(20)
        if solution is None:
            print "No answer found"
        else:
            print "found an answer:", solution
    

    On my computer, this finds an answer in under nine seconds.

    EDIT: And, if we take advice from David Zaslavsky, we realize we can start the loop at 2520, and step by 2520. If I do that, then on my computer I get the correct answer in about a tenth of a second.

    I made find_solution() take an argument. Try calling find_solution(2520).

    0 讨论(0)
提交回复
热议问题