質問

可能な複製:
JavaのサイズnのセットからK要素サブセットを繰り返し生成する方法は?

自分のポーカーハンド評価者を作りたいのですが、特定の部分に問題があります。

2人のプレイヤーが2枚のカードハンドを配られた場合、パックに48枚のカードが残っています。テキサスHold'emでは、さらに5つの可能なコミュニティカードが処理されます(これはボードと呼ばれます)。ボードの5つの可能な組み合わせを選択し、タイムズプレーヤーが勝利し、タイムズプレーヤーBが勝つタイムズプレーヤーを数える48すべてを列挙 /ループしたいと思います。

5枚のカードの組み合わせごとに体系的にループできる方法がわかりません。誰かがアイデアを持っていますか?カードはクラスカードの配列として表されますが、これがより速くなるとビットセットとして表現することもできます。

私はこれをJavaでやっています。

どうもありがとう

役に立ちましたか?

解決

(免責事項:非常に速いポーカーハンド評価者を書きました)

ボードの5つの可能な組み合わせを選択し、タイムズプレーヤーが勝利し、タイムズプレーヤーBが勝つタイムズプレーヤーを数える48すべてを列挙 /ループしたいと思います。

2人のプレイヤー間でマッチアップを行うたびに、C(48,5)(1 712 304)の手を評価したくありません。

たとえば、「AC AD」対「7C 6C」があるとしましょう。 1 333 573, 371 831, 6900 (1 333 573は「AC AD」が勝つ回数、371 831は「7C 6C」勝利数、6 900はネクタイ数(合計1 712 304)です。 6 900を捨てることができます。 c(48,5) - (勝利1 +勝利2).

(この回答の最後にあるルックアップテーブルの詳細)

しかし、あなたの質問に答えるために:

5枚のカードの組み合わせごとに体系的にループできる方法がわかりません。

すべての組み合わせを本当にループしたい場合は、ポーカーハンド評価者が通常、非常に高速である必要がある種類のプログラムであることを知っておく必要があります。これらのプログラムは通常、1秒あたりの数億の手を評価できます(あなたは正しく読みます:数億)。

このような高性能の「数のクランチ」が必要な場合は、「デザインパターン」と「OO」を忘れることができます。あなたが望むのは生の速度です。

たとえば、以下は最も内側のループC(48,5)を通過し、非常に高速です。

    for ( int i = 0; i < n; i++ ) {
        for ( int j = i + 1; j < n; j++ ) {
            for ( int k = j + 1; k < n; k++ ) {
                for (int l = k + 1; l < n; l++) {
                    for (int m = l + 1; m < n; m++) {
                        ...
                    }
                }
            }
        }
    }

再び2人のプレイヤーの場合、それはおそらく非常に悪い考えです:ルックアップテーブルを使用することではるかに速くなるでしょう。

しかし、3人のプレイヤーのpreflop(preflopテーブルを使用することは非現実的である場合、マッチアップが多すぎます)では、5つのネストされたループを使用して、C(46,5)の手でそのようにループすることをお勧めします(もちろん、必要なのは必要ですI、J、K、L、Mを使用して、残っている46枚のカードから正しい5枚のカードを取得します)。次に、5枚のカードを手に入れると、7つのうちの最高のハンド評価者(ボードの5つと各プレーヤーの2つ)を提供する高速ハンド評価者を使用します。

ルックアップテーブルについて:

ほとんどの人は、169対169のルックアップテーブル( "AC KD"、 "as kh"、 "ad ks"などを使用します。スタートハンドの)。 Wikipediaの記事では、169の非同等のスターティングハンドを取得する方法を説明しています。

http://en.wikipedia.org/wiki/texas_hold_%27em_starting_hands

あなたが取るとき、それらは同等ではありません 1 考慮に入れるが、あなたがするとすぐに ハンド1対ハンド2 「169 vs 169」は近似です(言ったと言ったのは非常に良いものです)。

もちろん、あなたはより空想的になることができます。 C(52,2)(1326)の実際の異なるhold'emのスターティングハンドのみがあります。つまり、最新のコンピューターに完全なルックアップテーブル(まったく近似なし)を構築することが非常に実用的です(C(1326,2)AINあなたが本当に完璧な数字が必要な場合。近似で暮らすことができる場合は、169対169のテーブル(C(169,2)または14の196エントリが必要です)に移動します。

他のヒント

  1. 配列の初期化(A)最初の5つのインデックスに。 (0,1,2,3,4)
  2. Aの最後のインデックスを次の位置に移動します。 A[k]++
  3. 次のインデックスを次の連続した位置に移動します。 (A[k+1] = A[k] + 1, 、...)。何らかのインデックスが大きくなりすぎる場合は、ステップ2の以前のインデックスで試してください。
  4. 現在のインデックスで要素を生成します A.
  5. 可能であれば、ステップ2から繰り返します。

イテレーターとして実装されています:

public class CombinationIterator<T>
        implements Iterable<List<T>>,
                   Iterator<List<T>> {
    private List<T> items;
    private int choose;
    private boolean started;
    private boolean finished;
    private int[] current;

    public CombinationIterator(List<T> items, int choose) {
        if (items == null || items.size() == 0) {
            throw new IllegalArgumentException("items");
        }
        if (choose <= 0 || choose > items.size()) {
            throw new IllegalArgumentException("choose");
        }
        this.items = items;
        this.choose = choose;
        this.finished = false;
    }

    public Iterator<List<T>> iterator() {
        return this;
    }

    public boolean hasNext() {
        return !finished;
    }

    public List<T> next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }

        if (current == null) {
            current = new int[choose];
            for (int i = 0; i < choose; i++) {
                current[i] = i;
            }
        }

        List<T> result = new ArrayList<T>(choose);
        for (int i = 0; i < choose; i++) {
            result.add(items.get(current[i]));
        }

        int n = items.size();
        finished = true;
        for (int i = choose - 1; i >= 0; i--) {
            if (current[i] < n - choose + i) {
                current[i]++;
                for (int j = i + 1; j < choose; j++) {
                    current[j] = current[i] - i + j;
                }
                finished = false;
                break;
            }
        }

        return result;
    }

    public void remove() {
        throw new UnsupportedOperationException();
    }
}

C#に相当する、イテレーター方法を使用してください。

public IEnumerable<IList<T>> Combinations<T>(IEnumerable<T> items, int choose)
{
    if (items == null) throw new ArgumentNullException("items");

    var itemsList = items.ToList();
    int n = itemsList.Count;

    if (n < 1) throw new ArgumentException("Must contain at least one item.", "items");
    if (choose <= 0 || choose >= n) throw new ArgumentOutOfRangeException("choose");

    var indices = Enumerable.Range(0, choose).ToArray();

    bool moreWork = true;
    while (moreWork)
    {
        yield return indices.Select(i => itemsList[i]).ToList();

        moreWork = false;
        for (int i = choose - 1; i >= 0; i--)
        {
            if (indices[i] < n - choose + i)
            {
                indices[i]++;
                for (int j = i + 1; j < choose; j++)
                {
                    indices[j] = indices[i] - i + j;
                }
                moreWork = true;
                break;
            }
        }
    }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top