カード組み合わせの総当りにCollections.shuffleを使う

Javaの小さなソース。

0以外の数字がひとつずつ書かれたカードをN枚並べて数を作る。
カードは重複する。

桁数を調節するための空白カードをN-1枚混ぜてランダムに抽選してN枚並べ、作った数を記録する。
数を作るたびにカードの状態は元に戻す。これを十分な回数繰り返す。

これまでに作られた数との同じ数が作られる(衝突)ことがあるので、それが連続して起こった回数を記録する。
最初のうちは衝突は稀にしか起こらないが、やがて十分な回数に近づくと新しい数は作られにくくなるので、連続して衝突が起こるようになる。

この仕組みで設定されたカードの並びで作ることができるすべての数を探す。

以下はN=6で1が3枚、2が1枚、3が2枚の場合で、十分な衝突の連続回数を1000000回として計算。

import java.util.*;
import java.lang.*;
import java.io.*;

class Test {

  public static void main(String[] args) throws java.lang.Exception {

    HashSet<Long> fixNumbers = new HashSet<Long>();
    List<String> cards = new ArrayList<String>();

    cards.add("1");
    cards.add("1");
    cards.add("1");
    cards.add("2");
    cards.add("3");
    cards.add("3");
    cards.add("");
    cards.add("");
    cards.add("");
    cards.add("");
    cards.add("");

    String word = "";
    long number = 0;
    long collision = 0;

    while (true) {

      Collections.shuffle(cards);

      word = "";
      for (int i = 0; i < Collections.frequency(cards, "") + 1; i++) {
        word += cards.get(i);
      }

      number = Long.parseLong(word);

      if (fixNumbers.add(number) != false) {
        collision = 0;
      } else {
        collision++;
      }

      if (collision >= 1000000) {
        System.out.println(fixNumbers.size());
        break;
      }

    }

  }
}