ええ本当に!?と疑問に思ったので、練習も兼ねてやってみました。
コイン分配問題 JavaScriptでやってみた
コイン分配問題
「有名な統計力学ゲーム」を実際に試してみる
「有名な統計力学ゲーム」をレーダーチャートで表示してみる
「有名な統計力学ゲーム」をcanvasで表示してみる
100000回試行し、プレイヤー毎の平均を表示してみます。
//関数fをかけ続けるジェネレーター
const nestG = f => function*( x ){
while( true ) {
yield x
x = f( x )
}
}
//ジェネレーターgの値をn個とりだすジェネレーター
const passTimesG = n => function*( g ){
let x
for(let i = 0; i<n; i++){
x = g.next();
if( x.done ) return;
yield x.value;
}
}
// xを初期値にジェネレーターを順次適用した結果をならべて配列にする
const pipeG = x => (...f) =>{
const spreadG = xs => [...xs]
const fs =[...f, spreadG]
return fs.reduce( (acc, e) => e(acc), x )
}
//配列の要素同士を足し合わせて新しい配列を返す
const zipAdd = xs => ys =>
xs.length < ys.length ? xs.map((e,i)=>e+ys[i]) : ys.map((e,i)=>xs[i]+e)
//一回分の試行。
const deal = state => {
const moveCoinOrNot = x => y => x > 0 ? [x-1, y+1] : [x, y]
const diceGen = () => Math.floor( Math.random() * 6 )
const loser = diceGen()
const winner = diceGen()
const newState = [...state];
if(loser === winner) return newState;
[ newState[loser], newState[winner] ] = moveCoinOrNot( state[loser] )( state[winner] )
return newState
}
//初期値
const state = [5,5,5,5,5,5]
const times =100000;
//試行を繰り返し、プレイヤー毎の平均を表示
pipeG(state)( nestG(deal), passTimesG(times) )
.reduce( (acc,e) => zipAdd( acc )( e ), [0,0,0,0,0,0] )
.map( e => e / ( times ) )
.forEach( e => console.log( e ) )
結果
試行回数をいろいろ変えてやってみました。
//試行の例
//10回:
7
4.8
4.1
5
4.7
4.4
// 100回:
2.93
3.94
5.85
5.09
11.06
1.13
//1000回:
3.628
4.426
4.927
10.415
1.876
4.728
//10000回:
3.5934
6.5859
6.1402
4.6628
4.1216
4.8961
//100000回;
5.60544
4.76653
5.30907
5.27514
4.44783
4.59599
100~1000回くらいまでは確かにけっこう差がでてくるようです。
10000回くらいになると差がなくなってきて、もっと多くなると有意な差は次第になくなってくるようです。