0
0

More than 3 years have passed since last update.

【Java】Fisher-Yatesのシャッフルで配列をシャッフルする

Posted at

はじめに

久しくプログラミング業務から離れているため、ちょっとしたアルゴリズムに触れて頭の体操をしようと思い立ち、Fisher-YatesのシャッフルをJavaで実装してみました。
アルゴリズムそのものは、Wikipediaに記載されているものを利用しています。

作成したコード

  • 以下のコードは、Wikipediaの改良されたアルゴリズムをJavaのコードとして書き起こしたものになります。
    • コード中のコメントは、Wikipediaに記載されているアルゴリズムと対応(一致)しています。
  • int型の配列をStreamにした後、そのままmapメソッドでStringにしようとするとエラーになりました。
    • こちらのサイトによると、int型配列をStreamにするとIntStreamになるものの、IntStreamではint型しか扱えないため、mapオブジェクトでString型に変換するとエラーが出てしまう...というのがエラーの理由だそうです。
    • そのため、mapToObjメソッドで各要素をString型にしています。
FisherYatesRefined.java
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * フィッシャー・イェーツのシャッフルの改良版
 * @author NKOJIMA
 *
 */
public class FisherYatesRefined {

    /**
     * 要素数がnの配列aryをシャッフルする(添字は0からn-1):
     * @param args
     */
    public static void main(String[] args) {

        int[] ary = {0,1,2,3,4,5,6,7,8,9};
        System.out.println("シャッフル前");

        System.out.println(Arrays.stream(ary).mapToObj(elem -> String.valueOf(elem)).collect(Collectors.joining(",")));

        int n = ary.length;
        Random rnd = new Random();

        // iをn-1から1まで減少させながら、以下を実行する
        for (int i=n-1; i>=1; i--) {
            // jに0以上i以下のランダムな整数を代入する
            int j = rnd.nextInt(i);

            // a[j]とa[i]を交換する
            int tmp = ary[i];
            ary[i] = ary[j];
            ary[j] = tmp;
        }

        System.out.println("シャッフル後");
        System.out.println(Arrays.stream(ary).mapToObj(elem -> String.valueOf(elem)).collect(Collectors.joining(",")));
    }

}

実行結果

  • 「シャッフル前」の結果は常に同じですが、「シャッフル後」の結果の並び順はシャッフルされていることが分かります。
実行結果
シャッフル前
0,1,2,3,4,5,6,7,8,9
シャッフル後
8,7,3,0,2,4,9,5,6,1

参考URL

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0