1: 2016-06-20 (月) 23:54:50 osinko |
2: 2016-06-21 (火) 02:41:08 osinko |
- | **コードで数え上げる の編集 [#t208b7de] | + | **コードで数え上げる [#t208b7de] |
| + | 確率の問題を考える |
| + | |
| + | コインを50回投げて表が連続8回、裏が連続8回と続けて出る確率は幾らか? |
| + | |
| + | |
| + | まず、問題の規模を小さくして考え易くする |
| + | コインを6回投げて表表裏裏と続けて出る確率は幾らか? |
| + | と言った風に考える |
| + | |
| + | PCとプログラムコードを利用して問題解決を試みる |
| + | まず実際にその事象の数を「数え上げて」みる |
| + | |
| + | 表をHead、'H'、裏をTail、'T'の一文字に抽象化して、その順列をコードで出力する |
| + | この出力に対して希望する条件に見合った事象を検索に掛け、その数を数え上げる |
| + | |
| + | 連続で変化する試行回数に沿って、その数の変化を観察し、その性質を見抜く |
| + | その上で、見抜いた性質に対し未来予測を試みて、実際にプログラムコードでシミュレーションし |
| + | その考えが正しいか否かを確認する。この一連の工程を通して計算した確率が「確からしい」事を確認する |
| + | (アプローチとしては理科の実験のように実際に体験していく形になっている) |
| + | |
| + | **問題を小さくして考える [#fc4c6021] |
| + | |
| + | まず、コインを4回投げた状態の順列を出力する。この場合、表表裏裏と言う事象は"HHTT"で表され、その順列は16事象中1事象となる筈だ。それを確認してみる。全体の順列を出力するプログラムコードは以下となる。このコードは帰納の考えを利用している。つまり数学的帰納による証明が行い易く、微積分に考えを転用しやすい。そのために帰納で作ったとも言えるし、運用性の点から帰納で作ったとも言える |
| + | |
| + | ***Perm.cs [#r3db5d73] |
| + | #code(csharp){{ |
| + | using UnityEngine; |
| + | using System.Collections; |
| + | using System.Collections.Generic; |
| + | using System.IO; |
| + | using System.Linq; |
| + | |
| + | public class Perm : MonoBehaviour |
| + | { |
| + | void Start() |
| + | { |
| + | int length = 4; |
| + | char[] set = { 'H', 'T' }; |
| + | |
| + | List<string> strList = Root(set, length); |
| + | |
| + | //全順列を網羅してファイル出力 |
| + | string folder = Application.dataPath; //これだけでunityの実行ファイルがあるフォルダがわかる |
| + | SaveText(folder, @"\順列.txt", strList.ToArray()); |
| + | |
| + | } |
| + | |
| + | //基底部 |
| + | List<string> Root(char[] set, int length) |
| + | { |
| + | List<string> strList = new List<string>(); |
| + | int level = 0; |
| + | |
| + | for (int i = 0; i < set.Length; i++) |
| + | { |
| + | char[] dat = new char[length]; |
| + | dat[0] = set[i]; |
| + | Loop(dat, level, set, strList); |
| + | } |
| + | |
| + | return strList; |
| + | } |
| + | |
| + | //帰納部 |
| + | void Loop(char[] dat, int level, char[] set, List<string> strList) |
| + | { |
| + | level++; |
| + | if (level < dat.Length) //帰納関数の終了条件 |
| + | { |
| + | for (int i = 0; i < set.Length; i++) |
| + | { |
| + | char[] cloneDat = (char[])dat.Clone(); //オブジェクトを複製する |
| + | cloneDat[level] = set[i]; |
| + | Loop(cloneDat, level, set, strList); //帰納関数には複製された参照値が渡される為、呼び出し元側の値が書き換えられることは無い |
| + | } |
| + | } |
| + | else { |
| + | strList.Add(new string(dat)); |
| + | } |
| + | } |
| + | |
| + | //資料:StreamWriter クラス (System.IO) |
| + | //http://msdn.microsoft.com/ja-jp/library/system.io.streamwriter(v=vs.110).aspx |
| + | |
| + | //テキストファイルとしてセーブ |
| + | public void SaveText(string fileFolder, string filename, string[] dataStr) |
| + | { |
| + | using (StreamWriter w = new StreamWriter(fileFolder + filename, false, System.Text.Encoding.GetEncoding("shift_jis"))) |
| + | { |
| + | foreach (var item in dataStr) |
| + | { |
| + | w.WriteLine(item); |
| + | } |
| + | } |
| + | } |
| + | } |
| + | }} |
| + | |
| + | これに対する出力ファイルの内容は以下となっている。VisualStudioでこのテキストファイルを開く。Ctrl+fで検索ウインドウを開き正規表現を使用するモードにして「HHTT」を検索すると、一つ見つける事が確認できる(正規表現(regex)モードにすると複数のラインが条件を満たした場合、複数のラインをマークする) |
| + | |
| + | HHHH |
| + | HHHT |
| + | HHTH |
| + | &font(Fuchsia){HHTT}; |
| + | HTHH |
| + | HTHT |
| + | HTTH |
| + | HTTT |
| + | THHH |
| + | THHT |
| + | THTH |
| + | THTT |
| + | TTHH |
| + | TTHT |
| + | TTTH |
| + | TTTT |
| + | |
| + | ここでコインを4回連続で投げた場合、全体16、表表裏裏(HHTT)が出る事象は1という事で確率が1/16である事が分かる。続けてコインを投げる回数を増やして、それぞれの回数でHHTTが出てくる回数を記録していく。投げる回数はコード内11行目、Start関数内のlengthの値を変更することで出来る |
| + | |
| + | int length = 5; |
| + | |
| + | この4のところを5,6,7,...と変更して検索を掛け回数を記録する。5を指定すると以下になる |
| + | |
| + | &ref(samp1.png); |
| + | |
| + | ある程度の回数まで進むと手動で検索するのが面倒になってくる |
| + | そこでコードを書いてプログラムに検索させる |
| + | #code(csharp){{ |
| + | void Start() |
| + | { |
| + | int length = 7; |
| + | char[] set = { 'H', 'T' }; |
| + | |
| + | List<string> strList = Root(set, length); |
| + | |
| + | //全順列を網羅してファイル出力 |
| + | string folder = Application.dataPath; //これだけでunityの実行ファイルがあるフォルダがわかる |
| + | SaveText(folder, @"\順列.txt", strList.ToArray()); |
| + | |
| + | //文字列の中に"HHTT"がある行を抜き出す |
| + | var queary = strList.AsQueryable().Where(item => item.Contains("HHTT")); |
| + | var queList = queary.ToList(); |
| + | queList.Add("カウント数" + queList.Count.ToString()); |
| + | SaveText(folder, @"\HHTT抜き出し.txt", queList.ToArray()); |
| + | } |
| + | }} |
| + | |
| + | これを15回ぐらいまで記録して以下のような表を作った |
| + | |
| + | |4回|5回|6回|7回|8回|9回|10回|11回|12回|13回|14回|15回| |
| + | |1/16| | | | | | | | | | | | |
| + | |
| + | この表の結果が正しいかどうかを確認する。実際にコンピューター内で50%ずつ表裏がランダムに出るコインを指定回数投げてHHTTが出た回数を数える。これを5回繰り返して値の様子を見る。このコードは以下になる |
| + | |
| + | ***niji_prob [#i2d517d8] |
| + | #code(csharp){{ |
| + | using UnityEngine; |
| + | using System.Collections; |
| + | using System.Collections.Generic; |
| + | using System.Linq; |
| + | |
| + | public class niji_prob : MonoBehaviour |
| + | { |
| + | |
| + | void Start() |
| + | { |
| + | int sampling = 10000; |
| + | int tossCount = 4; |
| + | float headPercentage = 0.5f; |
| + | string hitString = "HHTT"; |
| + | |
| + | char[] coinList = new char[tossCount]; |
| + | |
| + | for (int j = 0; j < 5; j++) |
| + | { |
| + | int successCount = 0; |
| + | |
| + | for (int i = 0; i < sampling; i++) |
| + | { |
| + | coinList = GetCoinTossTest(coinList, headPercentage); |
| + | if (new string(coinList).Contains(hitString)) successCount++; //文字列検索してマッチすればtrueを返しカウントアップ |
| + | } |
| + | print((double)successCount / (double)sampling); |
| + | } |
| + | } |
| + | |
| + | //動作確認用メソッド |
| + | private void SimpleMethod(float headPercentage, string hitString, char[] coinList) |
| + | { |
| + | coinList = GetCoinTossTest(coinList, headPercentage); |
| + | print(new string(coinList)); |
| + | print(new string(coinList).Contains(hitString)); |
| + | } |
| + | |
| + | //コイントス試行 |
| + | public char[] GetCoinTossTest(char[] coinList, float headPercentage) |
| + | { |
| + | for (int i = 0; i < coinList.Length; i++) |
| + | { |
| + | coinList[i] = TossCoin(headPercentage); |
| + | } |
| + | return coinList; |
| + | } |
| + | |
| + | //指定した表の確率でコイントスして表が出たら'H'(表:Head)、裏で'T'(裏:tail)を返す |
| + | public char TossCoin(float headPercent) |
| + | { |
| + | if (Random.value < headPercent) return 'H'; |
| + | return 'T'; |
| + | } |
| + | |
| + | } |
| + | }} |
| + | |
| + | 計算通りであるならばコインを4回投げた場合、1/16=0.065となる筈。おおよそその辺り周辺の値をフラフラしていれば、ほぼ正しいと考えられるだろう。出力結果は以下となった |
| + | ほぼ予想通り |
| + | |
| + | 0.0642 |
| + | 0.0652 |
| + | 0.06 |
| + | 0.0619 |
| + | 0.0606 |