[英]Get the index of a maximum value in a set number of iterations in Python's Itertools
(這是項目歐拉問題14)
我正在嘗試使用Itertools來豐富我的Python技能。
我想從Python的itertools中的生成器獲得一組迭代次數(1,000,000)中的最大返回值索引。
該功能有效,但我無法弄清楚如何有效地獲得最大值而不將其存儲在一個龐大的一百萬個長列表中,我認為這個列表很難有效。 有智能的智能方式嗎? (編輯:也許這是最簡單的方法?)
當前代碼是當鏈條達到100時它停止的那一刻是錯誤的。
#Project Euler Problem 14
#Which starting number, under one million, produces the longest chain?
import itertools
def length():
x=1
while True:
l=0
c=x #Create the running integer.
while c>1:
if c%2==0:
#Number is even, divide it by two.
c=c/2
l+=1
else:
#Number is odd, multiply by three and add one.
c=3*c+1
l+=1
yield l+1 #Add the final one as well and show the chain length.
x+=1 #Increment
print list(itertools.takewhile(lambda x:x<100,length()))
我解決了這個問題如下:
import functools
def euler_014(max_=1000000):
longest = max_len = None
for n in range(1, max_):
length = len_collatz(n)
if max_len is None or length > max_len:
max_len, longest = length, n
return longest
def memoize(f):
cache = {}
@functools.wraps(f)
def func(*args):
if args not in cache:
cache[args] = f(*args)
return cache[args]
return func
@memoize
def len_collatz(n):
if n == 1:
return 1
if n % 2:
n = (n * 3) + 1
else:
n //= 2
return 1 + len_collatz(n)
這里memoize
通過存儲len_collatz
先前結果使事情更有效, len_collatz
告訴你從n
到1
的序列長度(沒有實際生成整個序列的列表), euler_014
只需要跟蹤最長的長度和相關的價值n
。 請注意,它不會保留所有結果 - 只是到目前為止最長系列的長度和產生該序列的n
的值。
我在這里看不到使用itertools.take的理由。 Takewhile允許提前終止,但是你不能提前終止,因為你必須檢查每個n
不到一百萬的collatz(n)
。
標准max函數將在iterable中找到最高值。 范圍對象是在常量內存中工作的可迭代對象(即,它不使用范圍中所有值的內部列表。)。 我通常不會公開發布解決方案,但由於這只是前20個問題中的一個,而且這里已經發布了三個不同的解決方案......
def collatz(n):
return n // 2 if n%2 == 0 else 3*n + 1
def distance(n, cache={1:1}):
if n not in cache: cache[n] = distance(collatz(n)) + 1
return cache[n]
ans = max(range(1,1000000), key=distance)
print(ans)
你真的應該使用標准的max函數。 你不知道最長的鏈條有多長,所以第一個鏈條長於100不能保證工作。 這只是猜測和檢查。 Max發現最長而不將所有內容存儲在內存中。
我應該留下一個我記得“距離”的免責聲明。 這意味着我的代碼存儲至少1,000,000個值,因此不需要重復計算collatz(n)。 這需要花費幾MB的RAM,但會將執行時間從一分鍾縮短到幾秒鍾。 這非常值得。
用不同的方法添加第二個答案; 這個將使用生成器最小化內存占用量來生成collatz
序列。
但是,它要慢得多。 運行這個需要大約60秒,相比之下, memoize
d版本的第一次運行時為~5s(后續運行時為~1s,一旦cache
包含所有值),
def collatz(n):
while n > 1:
yield n
n = (n * 3) + 1 if n % 2 else n // 2
yield 1
def euler_014_iter(max_=1000000):
longest = max_len = None
for n in range(1, max_):
length = sum(1 for _ in collatz(n))
if max_len is None or length > max_len:
longest, max_len = n, length
return longest
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.