したがって、メインループで毎回行っていることは、各桁を 2 倍にしてから、余分な 10 を次の桁に繰り越すことです。問題は、最上位桁の次の桁が存在しないことです。
以下に説明する理由により、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
元のコードから 2 つの重要な変更があります。
まず、現在のキーではなく、ループの前に辞書のキーのセットのコピーを反復処理するため[:]
に、2 番目の の最後に追加する必要がありました。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
。
しかし、別のget
方法dict
を使用しました。デフォルト値を指定できる のメソッドです。理由は後で説明しますが、一般に、 に手を伸ばすとget
、代わりにdefaultdict
orが必要になる場合があることを覚えておいてください。Counter
これで、2 の累乗で実行され、機能します。しかし、2 つの理由から、他の累乗では機能しません。
まず、キャリーをランダムな順序で実行しています。2 の累乗の場合、運ぶことができるのは最大で 1 であり、1 が次の桁が上がるかどうかに影響を与える方法はありません。(8 はキャリーせず、8+1 もキャリーせず、現在は 9 を得る方法があります。) しかし、他のパワーの場合はそうではありません。
簡単なテストでは、これに気付かないかもしれません。(少なくとも CPython 2.7 と 3.2 では) 空のキーから始めて、dict
少数の小さなキー (実際にはハッシュ値が小さいが小さいキーints はソートされた順序で自分自身にハッシュされ、何も削除されませんdict
。多くの場合、順番に反復 (および出力) されます。しかし、一般に、順序は予測できず、信頼することはできません。
この問題の解決策はcollections.OrderedDict
、追加された順序でキーを反復処理する を使用することです。defaultdict
そして、それが私がor 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)