ランダムサンプルを使用して計算を近似する方法があります。このメソッドは何百万回も呼び出されるため、乱数を選択するプロセスが効率的であることが非常に重要です。
Java が実際にどれほど速いかはわかりRandom().nextInt
ませんが、私のプログラムは、私が望んでいるほどには恩恵を受けていないようです。
乱数を選択するときは、次のことを行います (半疑似コードで)。
// Repeat this 300000 times
Set set = new Set();
while(set.length != 5)
set.add(randomNumber(MIN,MAX));
さて、これは明らかに悪い最悪の場合の実行時間を持っています。理論的には、ランダム関数は永遠に重複した数値を追加できるため、whileループに永遠に留まる可能性があります。ただし、数値は {0..45} から選択されるため、値が重複することはほとんどありません。
上記の方法を使用すると、他の方法よりも 40% だけ速くなります。これは概算ではありませんが、正しい結果が得られます。これは約 100 万回実行されたので、この新しい方法は少なくとも 50% 高速になると予想していました。
より高速な方法について何か提案はありますか? あるいは、一連の乱数を生成するより効率的な方法を知っているかもしれません。
明確にするために、ここに2つの方法があります:
// Run through all combinations (1 million). This takes 5 seconds
for(int c1 = 0; c1 < deck.length; c1++){
for(int c2 = c1+1; c2 < deck.length; c2++){
for(int c3 = c2+1; c3 < deck.length; c3++){
for(int c4 = c3+1; c4 < deck.length; c4++){
for(int c5 = c4+1; c5 < deck.length; c5++){
enumeration(hands, cards, deck, c1, c2, c3, c4, c5);
}
}
}
}
}
// Approximate (300000 combinations). This takes 3 seconds
Random rand = new Random();
HashSet<Integer> set = new HashSet<Integer>();
int[] numbers = new int[5];
while(enumerations < 300000){
set.clear();
while(set.size() != 5){
set.add(rand.nextInt(deck.length));
}
Iterator<Integer> i = set.iterator();
int n = 0;
while(i.hasNext()){
numbers[n] = i.next();
n++;
}
いくつかのテストとプロファイリングの後、この方法が最も効果的であることがわかりました。
Random rand = new Random();
int[] numbers = new int[5];
ArrayList<Integer> list = new ArrayList<Integer>();
while(enumerations < 300000){
while(list.size() != 5) {
int i = rand.nextInt(deck.length);
if(!list.contains(i)) list.add(i);
}
int index = 0;
for(int i : list){ numbers[index] = i; index++; }
enumeration(hands, cards, deck,numbers);
}