只有result[p] < 10
Python的2或result[p] == 0
所以,你每次通過主環路做什麼:雙每個數字,然後再進行額外的幾十到下一個數字。問題在於,對於最高位數字,下一位數字不存在。
所以,這裏有一個解決方案 - 雖然它不適用於除2之外的任何電源,但出於我將在下面討論的原因。
def foo():
result={0:2}
for i in range(2,10):
for p in result.keys():
result[p]*=2
for p in result.keys()[:]:
if result[p]/10 != 0:
result[p+1] = result.get(p+1, 0) + result[p]/10
result[p] = result[p] % 10
從原始代碼有兩個關鍵的變化。
首先,我們必須添加[:]
到第二result.keys()
結束,在循環之前遍歷字典的一組密鑰的副本,而不是當前的密鑰。原因是,如果最後一位數字大於5,我們將添加一個新的密鑰到字典中,並且在迭代時不允許這樣做。 (爲什麼?有幾個原因,但最簡單的是詞典是以任意順序排列的,每次添加一個鍵時,整個順序都可以改變,這在以後也會變得很重要。)
二,原始問題:如何避免檢查if p+1 in result
以決定是否存儲r_p
或將r_p
添加到現有值?
當您處理計數時,您使用collection.Counter
,它與dict
類似,但它只存儲整數,並且任何缺少的鍵值都爲0。否則,您通常會使用collection.defaultdict
,它與dict
類似,不同之處在於您可以指定所有缺少的鍵都具有的默認值。通過Counter
或defaultdict
,您只需要result[p+1] += result[p]/10
。
但我已經使用了另一種方法:dict
上的get
方法,該方法允許您指定默認值。我會解釋爲什麼後面,但請記住,一般來說,當您發現自己達到get
時,您可能需要defaultdict
或Counter
。
所以,現在它會運行和工作,爲2的冪,但它不會對其他大國合作,原因有二:
首先,我們正在做的攜帶隨機順序。對於2的冪,你能攜帶的最多的是1,並且1不能影響下一個數字是否攜帶。 (8不會攜帶,8 + 1也不會,現在有辦法得到9)。但對於任何其他力量,這是不正確的。 (在CPython 2.7和3.2中),當你從一個空的dict
開始並添加少量的小鍵時(實際上,小鍵散列值,但小的ints散列到自己)以排序順序,並且不要刪除任何東西,dict
將經常迭代(和打印)的順序。但總的來說,訂單是不可預測的,你不能依賴它。
該問題的解決方案是使用collections.OrderedDict
,它按照添加它們的順序遍歷按鍵。這就是爲什麼我不想使用defaultdict
或Counter
:因爲如果您必須切換到OrderedDict
,您唯一的選擇是get
。第二,一旦你的指數超過10,你可能需要攜帶100.這意味着你必須攜帶10,這將導致下一個數字攜帶,即使它是0。這意味着我們不能只是提前複製密鑰。例如,假設我們正在做75的冪。從{0:5, 1:7}
開始。將每位數字乘以75至{0:375, 1:525}
。現在攜帶37:{0:5, 1:562}
。現在攜帶56:{0:5, 1:2, 2:56}
。因爲我們只是在迭代原始密鑰的副本 - 即[0, 1]
- 我們沒有機會攜帶這5個問題。我會給您解決該問題。
然而,你可能要考慮的一件事是創建一個新的字典,而不是修改舊的字典。那麼你可以解決所有這些問題。 (一般情況下,使用純函數而不是突變狀態都繞了很多問題,當然需要額外拷貝的成本)。
def double(d):
result = Counter()
for p in d:
result[p] += d[p] % 10
result[p+1] += d[p]/10
return result
digits={0:2}
for i in range(2,10):
for p in digits:
digits[p]*=2
digits = double(digits)
你的代碼張貼在設置'結果[P]',而不是'結果[p + 1]'。 – Amber
快速提問:爲什麼您使用字典'{0:2,1:1,2:5}'而不是列表'[2,1,5]'?無論哪種方式,'x [0] == 2','x [1] == 1','x [2] == 5'。 – abarnert
@Amber:抱歉,我不太明白,我的目標是將{0:16}設置爲{0:6,1:1},所以我必須同時更改... – acs