モンティ・ホール問題 AfterEffectsでシミュレーション・検証してみた (プログラム配布あり)
「モンティ・ホール問題」ご存知ですか?
たまにSNSや某掲示板などで取り上げられては、人々を惑わすこの問題。
モンティ・ホール問題とは…
あなたの前に扉が3つあります。 その扉の一つだけ、外に繋がっていて、他はハズレ。 最初に一つの扉を選んでください。 そうしたら私が、残り2つの扉のうち、ハズレの扉を教えます。 そして、もう一度だけ、選びなおしても良いです。 このときに、 A 選びなおさない B 選びなおす どちらの方が良いのか?
という問題です。
正解は
「 選びなおす 」
方が、正解の確率が高い。(文字を選択すると正解が現れます)
ググれば正解はすぐ出てきますが、知らない方は考えてみてください。
しかしここで、多くの人が疑問に思うはずです。
「本当にそれが正解なの?」「実際のところどうなの?」
ということで今回は、普通のプログラムではなく、Adobeの映像作成ソフトウェア、
”AfterEffects”で、モンティ・ホール問題のシミュレーションをして、検証してみたいと思います。
準備~エクスプレッションとは?~
今回使用する、AfterEffectsですが、前述の通り、映像制作のソフトです。
ただこのソフト内に、”エクスプレッション”という、スクリプト(Javascript)を記述して動かせる機能があります。
その機能をうまく使って、AfterEffects上に、この問題の結果を表示してみたいと思います。
そしてその結果から、今回の疑問の答えを導いていきます。
”エクスプレッション”とは、AfterEffects上で動くJavascriptなので、例えば、
このように、一般的なループの文(for文)と、エクスプレッション独自の関数を用いて、計算結果を、テキストに表示させたり、数値を代入して移動させたりなんかもできてしまいます。
エクセルにも”マクロ”という機能があり、一定の計算を自動で動かす機能がありますが、それと同じような機能です。
いちいち数値の入力が面倒な動作や、ループや継続的な運動、などを、手間なく実行したりできます。地震で揺れる表現なんかをするときは、Wiggle()なんていう、独自の関数を使うと、自動で揺らしてくれたりします。
それでは早速、プログラムを書いていきましょう。
実践
レイヤー構成
AfterEffectsには、Photoshopなどと同じく、”レイヤー”という概念があります。このレイヤーを、今回の検証が実現できるような構造に仕上げていきます。
1.テキストレイヤー:このレイヤーに、メインとなるエクスプレッション(スクリプト)を実装し、今回の結果を表示させます。
2.テキストレイヤー:結果の文字の賑やかしに使います。
3.平面レイヤー:背景 兼 数値を制御するためのエフェクトを適用します。
今回は、3つのレイヤーのとてもシンプルな構造になりました。
エクスプレッション制御エフェクト
今回は”スライダー”という、数値を制御できるエフェクトを適用しています。
”シード”というのは、ランダムな数を生成する際に、毎回同じ値になってしまうのを防ぐ、「ランダムのパターン」のような数値です。シードを変更してあげると、ランダムのパターンが変わり、別の数値に変わってくれます。
※本当は、テキストレイヤーに制御を適用しても動くのですが、レイヤーの役割を分けるために、平面レイヤーへ適用しました。
実際のスクリプト
それでは、テキストレイヤーに、核となるスクリプトを書いていきましょう。
今回は一応、「選びなおす」前提でプログラムを組んでいます。
こちらです(汚いコードお許しください…)↓
var s = 0;
var n = 0;
var out3 = 0;
var out5 = "";
var total = new Array();
var seed = thisComp.layer("暗いグリーン 平面 1").effect("シード")("スライダー");
var ttf = timeToFrames(t = time + thisComp.displayStartTime, fps = 1.0 / thisComp.frameDuration, isDuration = false) + 1;
for(s = 0; s < ttf; s++){
var coll = 0;
for(n = 0; n < 100 ; n++){
seedRandom(n + s + seed, true);
var arr = new Array();
arr[0] = 1;
for(var i=1; i < Math.floor( thisComp.layer("暗いグリーン 平面 1").effect("スライダー制御")("スライダー") ) ; i++){
arr[i] = 0;
}
for(var ii = arr.length - 1; ii > 0; ii--){
var r = Math.floor(Math.random() * (ii + 1));
var tmp = arr[ii];
arr[ii] = arr[r];
arr[r] = tmp;
}
var inp = Math.floor( random(0, i ) ) + 1;
var del = 0;
var val = false;
while(val === false){
del = Math.floor( random(0, i ) ) + 1;
if( del != inp && arr[del - 1] == 0 ){
val = true;
break;
}
}
var out1 = "";
var out2 = "";
for(var iii = 0;iii < arr.length ; iii++){
out1 = out1 + " " + arr[iii];
if( iii != (inp - 1 ) && iii != (del - 1) ){
out2 = arr[iii];
}
}
if(out2 == 1){
coll++;
}
}
out3 = out3 + coll;
out5 = out5 + " " + coll;
}
var out4 = (Math.floor( (out3 / ttf) * 100 ) ) / 100;
text.sourceText = "【計算 " + ttf + " 回】\r" + out1 + "\r選んだ扉 : " + inp + " 番目\r消した扉 : " + del + "番目\r(" + out5 + ")\r正解した数 : " + coll + " /100\r平均正解率 : " + out4 + " %";
Javascriptが分かる方でも、「thisComp」や「sourceText」など、見慣れない関数が出てくるのが分かると思いますが、これが、AfterEffects特有の関数です。
このコードが何をしているかを簡単に説明すると
① 3つの数値が入った配列 arr[ 1, 0, 0 ]を作る ② 配列 arr の中身をシャッフル ③ 3つのうち一つを選んで削除 ④ 選んだもの以外をランダムで選び”0”なら削除 ⑤ 残った数値を調べて”1”なら正解 ⑥ ①~⑤を100回繰り返して正解率を出す ⑦ 更に回数を重ねて平均正解率を導き出す →フレームを進めるごとに回数を重ねる
という動きをするコードです。
で、最後の
text.sourceText = "【計算 " + ttf + " 回】\r" + out1 + "\r選んだ扉 : " + inp + " 番目\r消した扉 : " + del + "番目\r(" + out5 + ")\r正解した数 : " + coll + " /100\r平均正解率 : " + out4 + " %";
で、テキストレイヤーの文字を書き換えてるわけです。
スクリプトが書けたので、”シード”の値を10回変えて、10回の正解率の平均を出してみましょう。
検証
10回(実質1000回の検証)の結果を以下に記します。
1回目 | 2回目 | 3回目 | 4回目 | 5回目 |
69 | 69 | 69 | 69 | 68 |
6回目 | 7回目 | 8回目 | 9回目 | 10回目 |
68 | 67 | 68 | 67 | 68 |
平均を出さなくても、結果が見えてきましたね。
正解率の平均は
68.2%でした!
つまり、モンティ・ホール問題の解
「選びなおす」は正しかった、ということが実証されました!!
まあ確率を出せば分かるんですが、やはり事実に基づく結果は、説得力が違うので、今まで正解を疑っていた人も、これで納得していただいたのではないでしょうか?
最後に、最終的な出力の画面をお見せして終わります。
プログラムファイルはこちらです
このように、Aftereffectsのエクスプレッションでは、映像制作以外にも、色々なことに使えるので、これからも色々と勉強を兼ねて、遊んでみたいと思います。
-
前の記事
素人がブランド立ち上げに挑戦! 其の1~ロゴデザイン part 1~ 2020.11.26
-
次の記事
映像制作におすすめのYouTubeチャンネル5選 2020.12.01