すごろく(6)

漸化式で確率を求める。
p0 = 1
p1 = 0
として、

 p_n = \frac{1}{36}((n-1)p_{0} + \cdots + p_{n-2}) \quad (2 \le n \le 7)
 p_n = \frac{1}{36}((13-n)p_{0} + \cdots + 6p_{n-7} + \cdots + p_{n-2}) \quad (8 \le n \le 11)
 p_n = \frac{1}{36}(p_{n-12} + \cdots + 6p_{n-7} + \cdots + p_{n-2}) \quad (12 \le n)

これをプログラムを書いて求めればいいが、どうしても数値誤差が出る。
しかし、割り算は36で割っているだけなので、36進数なら誤差は出ない。
ここは、表記しやすい6進数を使おう。
そうすると、

p[2] = 0.01
p[3] = 0.02
p[4] = 0.0301
p[5] = 0.0404
p[6] = 0.051401
p[7] = 0.103210
p[8] = 0.05553301
p[9] = 0.05333212
p[10] = 0.0515310001
p[100] = 0.05050505050505212...
p[1000] = 0.050505050505050505050505050505...

1/7は0.0505...である。
p1000は05が58個続く。
1/7に収束するのは間違いなさそうである。



var CARD = 6; // 基数
var NMASU = 1000;

Array.prototype.add = addNumber;
Array.prototype.multiply = multiplyNumber;
Array.prototype.divide = divideByCardinal;
Array.prototype.normalize = normalizeNumber;
Array.prototype.format = formatNumber;

var p = [ ];
init();
for(var i = 2; i <= NMASU; i++) {
p[i] = [ ];
for(var k = 1; k <= 6; k++)
p[i] = p[i].add(p[i+k-13].multiply(k));
for(var k = 5; k >= 1; k--)
p[i] = p[i].add(p[i-k-1].multiply(k));
p[i] = p[i].divide(2);
p[i].normalize();
print(p[i].format());
}


function init() {
for(var i = -10; i <= 2; i++)
p[i] = [ ];
p[0] = [ 1 ];
}

function formatNumber() {
if(this.length == 0) {
return "0";
}
else if(this.length == 1) {
return this[0] + "";
}
else {
var str = this[0] + ".";
for(var i = 1; i < this.length; i++)
str += this[i];
return str;
}
}

function addNumber(a) {
var b = [ ];
var length = Math.max(this.length, a.length);
for(var i = 0; i < length; i++)
b[i] = add(this[i], a[i]);
return b;
}

function multiplyNumber(a) {
var b = [ ];
for(var i = 0; i < this.length; i++)
b[i] = this[i] * a;
return b;
}

function divideByCardinal(nTimes) {
var b = this.slice(0);
for(var i = 0; i < nTimes; i++)
b.unshift(0);
return b;
}

function normalizeNumber() {
var d = 0; // 繰り上がり
for(var i = this.length - 1; i > 0; i--) {
this[i] += d;
d = Math.floor(this[i] / CARD);
this[i] -= d * CARD;
}
this[0] += d;
}

function add(a, b) {
if(a == undefined)
return b;
else if(b == undefined)
return a;
else
return a + b;
}

function print(str) {
WScript.Echo(str);
}