AP コンピューター サイエンス コースで、数日以内に次の課題を提出する必要があります。
「この課題では、ブルガリアン ソリティアのゲームをモデル化します。ゲームは 45 枚のカードから始まります。それらをランダムなサイズのいくつかの山にランダムに分割します。たとえば、サイズ 20、5、1、9、と 10. 各ラウンドで、各パイルから 1 枚のカードを取り、これらのカードで新しいパイルを形成します. たとえば、サンプルの開始構成は、サイズ 19、4、8、10、および 5 のパイルに変換されます. ソリティアは次のとおりです.パイルのサイズが 1、2、3、4、5、6、7、8、および 9 の場合は、ある順序でオーバーします。
プログラムで、ランダムな開始構成を作成して出力します。次に、ソリティア ステップを適用し続け、結果を出力します。ソリティアの最終構成に達したら停止してください。」
これを解決するプログラムを思いつきましたが、問題は非常に長い時間がかかることです。それ以外の場合は、予想どおりほぼ瞬時に解決されますが、18,000 回以上の反復が可能な場合もあります。
http://mancala.wikia.com/wiki/Bulgarian_Solitaireによると、解は (k^2)-k ステップ以下で見つけることができます。この場合、k は 9 です。多くの場合、72 ステップ以下で解決策を見つけることはできません。私はこのプログラムを何時間も見て、高速化できるかどうかを確認するためにさまざまなことをいじりましたが、十分な回数の反復で動作させることができません。だから今、スタック オーバーフローに来て、誰かが私を正しい方向に押し進めるのを手伝ってくれるかどうかを確認しました。
これが私のコードです:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
public class BulgarianSolitaire {
ArrayList<Integer> cards = new ArrayList<Integer>();
Random rand = new Random();
boolean cont = true;
boolean cont2 = true;
public static void main(String[] args) {
BulgarianSolitaire game = new BulgarianSolitaire();
}
public BulgarianSolitaire() {
System.out.println("Started");
int sum = 0;
while (cont) {
if (sum < 45) {
cards.add(rand.nextInt(46 - sum));
} else {
cont = false;
}
sum = 0;
for (int i = 0; i < cards.size(); i++) {
sum += cards.get(i);
}
removeZeros(cards);
System.out.println(cards);
}
System.out.println("Finished Generating Start");
while (cont2) {
solitaireStep();
System.out.println(cards);
if (checkCards()) {
cont2 = false;
}
}
Collections.sort(cards);
System.out.println("Cards are sorted");
System.out.println(cards);
}
public void removeZeros(ArrayList<Integer> list) {
for (int j = 0; j < list.size(); j++) {
if (list.get(j) == 0) {
list.remove(j);
}
}
}
public void solitaireStep() {
int numberRemoved = 0;
for (int i = 0; i < cards.size(); i++) {
int value = cards.get(i);
cards.set(i, value - 1);
removeZeros(cards);
numberRemoved++;
}
cards.add(numberRemoved);
}
public boolean checkCards() {
ArrayList<Integer> expectedCards = new ArrayList<Integer>();
for (int i = 1; i < 10; i++) {
expectedCards.add(i);
}
ArrayList<Integer> sortedCards = cards;
Collections.sort(sortedCards);
boolean equal = true;
if (sortedCards.size() != expectedCards.size()) {
equal = false;
}
for (int i = 0; i < sortedCards.size(); i++) {
if (sortedCards.size() == expectedCards.size()) {
if (sortedCards.get(i) != expectedCards.get(i)) {
equal = false;
}
}
}
return equal;
}
}
だから私は基本的に 0 から 45 の間の乱数を生成することから始めて、それをカードのリストに追加します。次に、乱数の生成を続け、合計が 45 未満である限り、生成された乱数が 0 から 45 (最後の反復での数値の合計) になるように、乱数を生成してリストに追加します。リスト内のゼロも同様に削除されます。
リストが生成されると、リスト内のすべての数値から 1 を減算し、ゼロを削除して、減少したスタックの数に等しい新しい値を追加するステップが実行されます。また、リスト {1, 2, 3, 4, 5, 6, 7, 8, 9} に対してカード スタックの順序付けられたバージョンをチェックし、一致が見つかると、ブール値の cont2 を false に設定して、そのソリティアステップの実行を停止します。
それはそれについてです。助けてくれる人に感謝します。