その点, シミュレータはプログラムをしっかり書けば何回でも正しく処理できる.
Winning WaysにはElena Conwayが好んだパターンを作る手順が書いてある. どんなパターンか興味があったが, シミュレータを使えばそのパターンを作るのは簡単であった.
手順は省略する. Winning Ways, Vol. 4, p. 876参照.
((0 2 8 6) (1 5 7 3) (15 24 33 42) (12 21 30 39) (9 18 27 36))のような置換のリストがある. つまり面0は2へ行き, 2は8へ行き, 8は6へ行き, 6は0へ行くを示す. t-はこのリストを逆に読む. まだ前途遼遠だが, 出来たところまでをまずアップロードしよう.
(define (test n ps is js) (define (up ps) (caddr (list-ref ps 5))) (define (left ps) (cadar ps)) (define (try *????) (for-each (lambda (x) (let ((p (car x)) (i (caadr x)) (j (cadadr x))) (if (not (member i is)) (test (+ n 1) (cons p ps) (cons i is) (cons j js))))) *????)) (case n ((0) (try *2??2)) ((1 2 3 4) (case (left ps) ((0) (try *2??0)) ((1) (try *2??1)) ((2) (try *2??2)))) ((5) (case (left ps) ((0) (try *22?0)) ((1) (try *22?1)) ((2) (try *22?2)))) ((6 12) (case (up ps) ((0) (try *0??2)) ((1) (try *1??2)) ((2) (try *2??2))))
((24) (begin (display ps) (newline) (display is) (newline) (display js)) (newline))))
<html> <head> <title>nth day after birth</title> <script language="JavaScript">
function quotient(a,b){
var r=a%b;
var q=(a-r)/b;
return q;}
var mon0=[0,31,59,90,120,151,181,212,243,273,304,334]; var mon1=[0,31,60,91,121,152,182,213,244,274,305,335];
function rd(y,m,d){
var a=(y-1)*365;
var b=quotient(y+3,4);
var c=quotient(y,400)-quotient(y,100);
var f=(((y%100)==0)?((y%400)==0):((y%4)==0))?mon1[m-1]:
mon0[m-1];
return a+b+c+f+d-1;}
function gr(rd){
var d0=rd+366-1;
var y400=quotient(d0,146097);
var d1=d0%146097;
var y100=quotient(d1/36524.25,1);
var d2=d1-146097+quotient(36524.25*(4-y100),1);
var y4=(y100==0)?quotient(d2,1461):
(24-quotient((36523-d2)/1460.96,1));
var d3=(y100==0)?(d2%1461):(d2-quotient(y4*1460.96,1));
var y1=((y100>0)&&(y4==0))?quotient(d3,365):
quotient(d3/365.25,1);
var d4=((y100>0)&&(y4==0))?d3%365:
(d3-1461+quotient(365.25*(4-y1),1));
var y=y400*400+y100*100+y4*4+y1;
var leap=((y%100)==0)?((y%400)==0):((y%4)==0);
var e=leap?mon1:mon0;
var mon=0;
for(i=0;e[i]<=d4;i++){mon=mon+1;}
var d=d4-e[mon-1]+1;
document.write(y.toString(10)+" "+mon.toString(10)+" "
+d.toString(10));
document.write("<br>");}
</script>
</head>
<body>
<script language="JavaScript">
document.write("<br>");
var s,i,y,m,d,n;
s = prompt("Type in your birthyear,birthmonth,birthday and n
as `2000,1,1,1000' without space", "");
i = s.indexOf(',');
y = s.substring(0,i);
s = s.substring(i+1,s.length);
i = s.indexOf(',');
m = s.substring(0,i);
s = s.substring(i+1,s.length);
i = s.indexOf(',');
d = s.substring(0,i);
n = s.substring(i+1,s.length);
document.write("y = " + y);document.write("<br>");
document.write("m = " + m);document.write("<br>");
document.write("d = " + d);document.write("<br>");
document.write("n = " + n);document.write("<br>");
y=y-0;
m=m-0;
d=d-0;
n=n-0;
var r=rd(y,m,d);
document.write("Your "+ n.toString(10) +"th day is ");
gr(r+n);document.write("<br>");
</script>
</body>
</html>
y = 1912 m = 6 d = 23 n = 15000 Your 15000th day is 1953 7 18
(define c (expt 10 100)) (do ((n 1 (+ n 2))) ((< (/ c n (expt 5 n)) 1) n)) => 141 (do ((n 1 (+ n 2))) ((< (/ c n (expt 239 n)) 1) n)) => 43これで必要な項数は判ったので, 105桁のbignumで計算する. aは tan-1(1/5), bはtan-1(1/239)で, 最後にaの16倍からbの4倍を引き, 最後の5桁を捨てる. opはループで毎回0と1に切り替わりそれに従って次の項を足したり引いたりする.
(define c (expt 10 105)) (define op 0) (define a 0) (do ((n 1 (+ n 2))) ((= n 143)) (set! a ((if (= op 0) + -) a (quotient (quotient c n) (expt 5 n)))) (set! op (- 1 op))) (define op 0) (define b 0) (do ((n 1 (+ n 2))) ((= n 45)) (set! b ((if (= op 0) + -) b (quotient (quotient c n) (expt 239 n)))) (set! op (- 1 op))) (quotient (- (* a 16) (* b 4)) 100000)で結果は
314159265358979323846264338327950288419716939937510 58209749445923078164062862089986280348253421170679πの100桁, 1000桁の値はすぐに見付かる. 私は城, 牧之内「計算機械」にあったのを知っているので書棚から取り出し同じであることを確認した.