10

1 億以上の文字列の膨大なリストを管理するにはどうすればよいですか? このような巨大なリストで作業を開始するにはどうすればよいですか?

大きなリストの例:

cards = [
            "2s","3s","4s","5s","6s","7s","8s","9s","10s","Js","Qs","Ks","As"
            "2h","3h","4h","5h","6h","7h","8h","9h","10h","Jh","Qh","Kh","Ah"
            "2d","3d","4d","5d","6d","7d","8d","9d","10d","Jd","Qd","Kd","Ad"
            "2c","3c","4c","5c","6c","7c","8c","9c","10c","Jc","Qc","Kc","Ac"
           ]

from itertools import combinations

cardsInHand = 7
hands = list(combinations(cards,  cardsInHand))

print str(len(hands)) + " hand combinations in texas holdem poker"
4

5 に答える 5

11

たくさんのメモリを備えています。Python のリストと文字列は実際にはかなり効率的であるため、メモリがあれば問題にはなりません。

とはいえ、保存しているのが特にポーカー ハンドである場合は、よりコンパクトな表現を思い付くことができます。たとえば、1 バイトを使用して各カードをエンコードできます。つまり、ハンド全体を格納するのに 1 つの 64 ビット int だけが必要です。次に、これらを NumPy 配列に格納できます。これは、Python リストよりもはるかに効率的です。

例えば:

>>> cards_to_bytes = dict((card, num) for (num, card) in enumerate(cards))
>>> import numpy as np
>>> hands = np.zeros(133784560, dtype='7int8') # 133784560 == 52c7
>>> for num, hand in enumerate(itertools.combinations(cards, 7)):
...     hands[num] = [cards_to_bytes[card] for card in hand]

そして、最後の行を少し高速化するには:hands[num] = map(cards_to_bytes.__getitem__, hand)

これには 7 * 133784560 = ~1GB のメモリしか必要ありません…そして、各バイトに 4 枚のカードをパックすれば、それを削減できます (頭のてっぺんからそれを行うための構文がわかりません…)

于 2013-03-07T23:30:29.030 に答える
3

処理用のデータ ストリームを自由に作成できるもう 1 つのメモリレス オプションは、ジェネレータを使用することです。例えば。

ハンドの総数を出力します。

sum (1 for x in combinations(cards, 7))

クラブのエースが含まれる手の数を出力せよ:

sum (1 for x in combinations(cards, 7) if 'Ac' in x)
于 2013-03-14T21:54:43.480 に答える
1

多くの場合、コーディングに費やす時間とコードの実行にかかる時間の間にはトレードオフがあります。何かをすばやく完了させようとしていて、頻繁に実行することを期待していない場合は、提案しているようなアプローチで問題ありません。リストを巨大なものにしてください。十分な RAM がないと、システムは仮想メモリを大量に消費しますが、より洗練されたソリューションの書き方を学ぶよりも早く答えを得ることができるでしょう。

しかし、これが定期的に使用されると予想されるシステムである場合は、すべてを RAM に格納する以外の方法を考え出す必要があります。おそらく SQL データベースが必要です。それらは非常に複雑になる可能性がありますが、ほぼどこにでもあるため、優れたチュートリアルがたくさんあります。

ORMレイヤーを介してデータベースへのアクセスを簡素化するdjangoのような十分に文書化されたフレームワークに目を向けるかもしれません。

于 2013-03-07T23:37:48.473 に答える
0

私のパブリック ドメインの OneJokerライブラリには、便利な組み合わせ関数がいくつかあります。組み合わせのセットに関する情報を、それらを保存したり実行したりすることなく提供できる Iterator クラスがあります。例えば:

  import onejoker as oj
  deck = oj.Sequence(52)
  deck.fill()

  hands = oj.Iterator(deck, 5)    # I want combinations of 5 cards out of that deck

  t = hands.total                 # How many are there?
  r = hands.rank("AcKsThAd3c")    # At what position will this hand appear?
  h = hands.hand_at(1000)         # What will the 1000th hand be?

  for h in hands.all():           # Do something with all of them
     dosomething(h)               

Iterator.rank() 関数を使用して各ハンドを単一の int に減らし、それらをコンパクトな配列に格納してから、Iterator.hand_at() を使用してオンデマンドで生成することができます。

于 2013-03-26T06:03:48.217 に答える