これにより、@GreggLind の優れたソリューションにいくつかの最適化が追加され、実行時間が半分に短縮されます。
def is_palindrome(n):
s = str(n)
return s == s[::-1]
def biggest():
big_x, big_y, max_seen = 0,0, 0
for x in xrange(999,99,-1):
# Optim. 1: Nothing in any row from here on can be bigger.
if x*x < max_seen: break
for y in xrange(x, 99,-1): # so we don't double count
# Optim. 2: break, not continue
if x*y < max_seen: break # since we're decreasing,
# nothing else in the row can be bigger
if is_palindrome(x*y):
big_x, big_y, max_seen = x,y, x*y
return big_x,big_y,max_seen
biggest()
# (993, 913, 906609)
この線
if x*x < max_seen: break
x がこれまでに見た最大の回文の sqrt よりも小さい点に到達すると、その行の要素をそれ以上調査する必要がないだけでなく、残りのすべての行は x の現在の値よりも小さい数値から始まるため、これ以上行を調査する必要さえありません。
これは を呼び出す回数を減らすわけではありませんis_palindrome()
が、外側のループの反復回数が大幅に減ることを意味します。それが壊れるの値x
は 952 であるため、853 行のチェックを省略しました (他の のおかげで「小さい」行ではありますがbreak
)。
ということにも気づきました
if x*y < max_seen: continue
する必要があります
if x*y < max_seen: break
内側のループの現在の反復だけでなく、行全体を短絡しようとしています。
cProfileを使用してこのスクリプトを実行したとき、最適化前の累積時間はbiggest()
平均で約 56 ミリ秒でした。最適化により、約 23 ミリ秒に短縮されました。どちらの最適化だけでも改善のほとんどは実現できますが、最初の最適化は 2 番目の最適化よりもわずかに役立ちます。