2012-09-03 24 views
1

我一直在研究Euler project problem 4,我的代碼工作正常,但它需要很多時間(0.41秒)。我怎樣才能優化它,這樣會花費更少的時間。有沒有我錯過的技巧,或者我不知道的特殊功能?
這是代碼:我該如何優化Python代碼:歐拉項目概述4

#Note: tpal is a function to test if number is palindrome 

pal =0 

for i in range(999,100,-1): 
    if pal >= i*999: #A way to get out of loop and to not test on all numbers 
     break 
    for j in range(999,100,-1): 
     if pal >= i*999: 
      break 
     if j > i:       #numbers would already have been tested so I skip them 
      continue 
     pot=i*j 
     if ((tpal(pot)==1)and(pot> pal)): 
      pal=pot 
      i1=i 
      j1=j 

print(i1,j1,pal) 

def tpal(num): 
    num=list(str(num)) 
    Le=len(num) 
    if Le == 1: # if number is of one digit than palindrome 
     return 1 

    le=len(num) 

    if le%2 !=0: #4 example 10101even nbr 
     le-=1 
    le/2  

    for i in range(0,le): 
     if num[i]!=num[Le-i-1]: 
      return 0 

    return 1     
+0

至少,你可以用j = i開始內部循環。 – sshannin

+6

31秒?有些事情是非常非常錯誤的。你的代碼對我來說需要0.1s,而且即使是一個完全沒有優化的1線程也只需要0.8s。你的'tpal'函數是什麼樣的? – DSM

+0

輸出結果應該是什麼? – arshajii

回答

2

現在,事實證明代碼已經運行了一段時間,但它不再那麼有趣。你可以修改代碼來測試更少的數字並儘早放棄。但有一個明顯的優化是可愛的。此行:

 if ((tpal(pot)==1)and(pot> pal)): 

檢查每次是否有迴文,即使pot <= pal。迴文測試是昂貴的。如果你簡單地交換順序:(注意,您不需要==1):

 if (pot > pal) and tpal(pot): 

,那麼你可以節省大量的時間:

In [24]: timeit orig() 
1 loops, best of 3: 201 ms per loop 

In [25]: timeit orig_swapped() 
10 loops, best of 3: 30.1 ms per loop 

因爲A and B如果A不探討B已經是假的,所以它知道A and B必須是假的。 (這就是所謂的「短路」;同樣的事情發生與「A或B」如果A是真的。)

順便說一句,這裏的最後一行:

if le%2 !=0: #4 example 10101even nbr 
    le-=1 
le/2  
^^^^ 

不會改變le。我認爲這三條線意味着相當於le //= 2

+0

哦,整潔的想法;通過交換兩件簡單的事情,代碼的速度可以變得相當快。 – arshajii

0

沒有給你全部答案。這裏有一些指針。

  • 重新考慮你的for循環,它們是複雜的方式。也許內循環應該從i開始?
  • 刪除所有這些愚蠢的句子,如果你的循環是正確的,你不需要它們。
  • 最後,int(str(pot)[::-1])==pot那麼它的迴文

編輯: 讓男人/女人,解決這個問題他/她的自我。無需在這裏發佈解決方案。

1

試試這個,它不應該採取近等長31個秒時:

def isPalindrome(n): 
    return str(n) == str(n)[::-1] 

def listNums(): 
    a, b, pal = 0, 0, 0; 
    for i in range(999, 99, -1): 
     for j in range(999, 99, -1): 
      n = i * j 
      if isPalindrome(n) and n > pal: # better to use "n > pal and isPalindrome(n)" instead, see other answer for details. 
       a, b, pal = i, j, n 
    return a, b, pal    

print listNums() 

運行這大概需要1秒鐘。對於這樣的事情,你肯定不需要在你的循環中使用多餘的if語句 - 如果你循環訪問,比如range(9999, 999, -1),你可以考慮進行一些這樣的優化(當然,可以進行許多潛在的優化到這樣的事情,例如不循環每個我,j對兩次)。