RM-BLOG

IT系技術職のおっさんがIT技術とかライブとか日常とか雑多に語るブログです。* 本ブログに書かれている内容は個人の意見・感想であり、特定の組織に属するものではありません。/All opinions are my own.*

【MONOEYES】Run Run連続再生の確率

A Mirage In The Sun - MONOEYES
A Mirage In The Sun - MONOEYES

実はMONOEYES「A Mirage In The Sun」収録の「Run Run」を、俺は2曲持っている。
A Mirage In The Sunを購入するよりも前にiTunesでRun Runだけ購入してしまったのである。
その後になってA Mirage In The Sunを購入・iTunesライブラリにインポートしたので、
結果的に「A Mirage In The Sun」の「Run Run」が俺のiTunesライブラリ上では全く同じ曲が2曲存在していることになっている。

要するにRun Run1曲分余分に金を使っていることになる(あほ)。
Run Runを結構気に入ってしまって、PVばっか見ていたのだが、
あほらしくなったのでRun Runだけ買っちまえ!
⇒めっちゃええやんアルバムごと買っちまえ!
という経緯によるものである。

こういう場合、A Mirage In The Sun全体をシャッフル再生すると、
当然「Run Run」だけはどっかで2回流れることになるが、
そうなるとこの確率はどんなもんなんだ?というのが(懲りずに)また少し気になり始めた。
というのもどうもA Mirage In The Sunシャッフルをしていると、
Run Runが連続する確率が高いように感じたのである。
以前の検証において、ストレイテナーのSILLY PARADEが連続する確率は0.00367%という計算結果が出ているが
これは母体の数がA Mirage In The Sunとは比べ物にならないほど大きい(ストレイテナー全手持ちの曲257曲(当時))からであり
A Mirage In The Sun収録の12曲(実態としてRun Runが1曲かぶってるので俺のiTunesライブラリ上では13曲になっている)を母体数とすれば
ストレイテナーのSILLY PARADE連続よりは確率が高いことは明らかである。
1曲かぶっているRun Runが連続する確率はどれくらいか?
調べてみた。


 

 


まずは理論値から追ってみる。
A Mirage In The Sunに収録されているのは12曲だが、Run Runが被ってるので全部で13曲になる。
この13曲をランダムで再生するとき、「Run Run」がどこかのタイミングで連続するケースを考えればよい。

例えば以下のようなケースが考えられる(便宜上、かぶっているRun Runを(1)と(2)でわけている)
(1)Run Run(1)⇒Run Run(2)⇒他11曲
この確率は

1/13*1/12*11/11*10/10*…*1/1
=1/13*1/12


で計算される。
最初の2曲はRun Run(1)が1/13、Run Run(2)が1/12の確率となり、
最初の2曲でRun Runが出そろったので残り11曲は何が流れてもいい計算である。

ここで、Run Run(1)とRun Run(2)は厳密に2曲を分けた考え方であり、
連続さえしていればその順番は問わない(Run Run(2)⇒Run Run(1)でもいい)ため
この確率は順序逆転版も考慮すると2倍になる。
よってこのケースでのRun Run連続再生確率は


1/13*1/12*2
≒0.012821…


となる。百分率にすると約1.3%弱というところである。この時点で割と高い。

同様の連続ケースは
(2)Run Run2曲を除く11曲のどれか⇒Run Run(1)⇒Run Run(2)⇒残り9曲のどれか
(3)Run Run2曲を除く11曲のどれか⇒Run Run2曲を除く残り10曲のどれか⇒Run Run(1)⇒Run Run(2)⇒残り8曲のどれか

というように連続する部分を1つずつずらしていくと全12ケースを考えることができる。
計算してみればわかるのだが各ケースで↑と同じ確率が導かれるので、
全体として「Run Runが連続する確率」は


(1/13*1/12*2)*12
≒0.153846…


という計算結果になる。
百分率で表すと約15.4%。これはかなり高い。




本当にこのくらいの確率になるのか、簡単なシミュレータプログラムを作って検証してみる。
プログラムは以下のとおりである。

import java.util.*;
import java.text.*;
import java.io.*;

public class AMirageInTheSunShuffleSimulation {
	
	
	private static final File RESULT_FILE = new File("shuffle_result.txt");
	private static final int SIMULATE_COUNT = 100000;
	
	private static final DateFormat YYYYMMDDHHmmSSsss = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
	private static final int LOG_COUNT = 10000;
	
	private static final String[] A_Mirage_In_The_Sun = new String[] {
		"Cold Reaction"
		,"Like We've Never Lost"
		,"Just A Little More Time"
		,"My Instant Song"
		,"Run Run(1)"
		,"Run Run(2)"
		,"グラニート"
		,"End Of The Story"
		,"Do I Have To Bleed Again"
		,"Get Me Down"
		,"明日公園で"
		,"Wish It Was Snowing Out"
		,"Remember Me"
	};
	
	public static void main(String[] args) {
		try {
			printLog("1.Start");
			
			shuffleSimulation();
			
			printLog("2.End");
		} catch(Throwable e) {
			e.printStackTrace();
		}
	}
	
	private static void shuffleSimulation() throws Throwable {
		BufferedWriter bw = null;
		int runrunContinuityCount = 0;
		try {
			bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(RESULT_FILE)));
			
			for (int i=0; i < SIMULATE_COUNT; i++) {
				// 今回曲目リストを取得
				String musicListString = makeShuffleList();
				// Run Runが連続しているかチェック
				boolean isRunRunContinuity = isRunRunContinuity(musicListString);
				if(isRunRunContinuity) {
					runrunContinuityCount++;
				}
				
				// 結果ファイルへの出力文字列を生成
				StringBuilder sb = new StringBuilder();
				sb.append(String.valueOf(i+1));
				sb.append("	");
				sb.append(String.valueOf(isRunRunContinuity == true ? "○" : "×"));
				
				String[] musicArray = musicListString.split("\t");
				for (int j=0; j < musicArray.length; j++) {
					sb.append("	");
					sb.append(musicArray[j]);
				}
				
				bw.write(sb.toString());
				bw.newLine();
				bw.flush();
				
				if (i > 0 &&  i % LOG_COUNT == 0) {
					printLog("	Current Round[" + String.valueOf(i) + "]");
				}
			}
			double runrunContinuityProbability = (double)runrunContinuityCount / (double)SIMULATE_COUNT * 100.00;
			DecimalFormat dc = new DecimalFormat("00.000");
			printLog("総シャッフル回数   :" + String.valueOf(SIMULATE_COUNT));
			printLog("Run Run連続回数    :" + String.valueOf(runrunContinuityCount));
			printLog("Run Run連続再生確率:" + dc.format(runrunContinuityProbability) + "%");
			
		} catch(Throwable e) {
			throw e;
		} finally {
			if (bw != null) {
				bw.close();
			}
		}
	}
	
	private static String makeShuffleList() {
		List musicList = new ArrayList();
		for (int i=0; i < A_Mirage_In_The_Sun.length; i++) {
			musicList.add(A_Mirage_In_The_Sun[i]);
		}
		
		StringBuilder musicListString = new StringBuilder();
		while (musicList.size() > 0) {
			int randomIndex = (int)(Math.random() * musicList.size());
			String music = musicList.get(randomIndex);
			musicList.remove(randomIndex);
			
			musicListString.append(music);
			musicListString.append("	");
		}
		
		return musicListString.substring(0 , musicListString.length() - 1);
	}
	
	private static boolean isRunRunContinuity(String musicListString) {
		boolean result = false;
		String beforeMusic = "";
		String[] musicArray = musicListString.split("\t");
		
		for (int i=0; i < musicArray.length; i++) {
			
			// 1曲目ならbeforeMusicに曲名設定して速攻で次の曲へ
			if (i == 0) {
				beforeMusic = musicArray[i];
				continue;
			}
			// 今の曲と前の曲がともに「Run Run」で始まってたら連続とみなす
			String currentMusic = musicArray[i];
			if (beforeMusic.startsWith("Run Run") && currentMusic.startsWith("Run Run")) {
				return true;
			} else {
				beforeMusic = currentMusic;
			}
			
		}
		
		return false;
	}
	
	private static void printLog(Object msg) {
		StringBuilder sb = new StringBuilder();
		sb.append(YYYYMMDDHHmmSSsss.format(new Date()));
		sb.append(" ");
		if (msg != null) {
			sb.append(msg.toString());
		}
		
		System.out.println(sb.toString());
	}
	
	
}


100,000(10万回)シャッフルしてその中で「Run Run」が何回連続するかを計算する。
各回でRun Runが連続したかどうかを○か×であらわし、その曲目リストそのものをTAB区切りで繋げてファイルにも出力している。
結果は15.439%となった。
理論値に比較的近い(理論値よりは少し高めだ)が概ね予想通りといったところである。




というわけで約15.4%の確率でRun Runが連続することになるようだ。
つまり100回シャッフル再生したらうち15回はRun Runが連続している可能性が高いことになる。
10回シャッフル再生してもうち最低1回はRun Runが連続している可能性が高いとみなせる。
そりゃ高頻度だなと感じるだろう。
冒頭述べたとおりストレイテナーのSILLY PARADEと比べると、
母体数の違いもあってはるかに高い確率となった。

こうした事情もあってかRun Runを聴きすぎて最早歌詞を暗記してしまった。
昔のSpace Sonicに近いものがある。
どうでもいいけど細美って英語歌詞にやたら「just」を使う気がする。
気のせいかね。