(cache) アルゴリズム基礎論演習2009
課題13 「格子点(ランダム)」
内容
課題3では、1≦x≦n, 1≦y≦n の全ての格子点に対して原点から見えるかどうかを判定し、
原点から見える格子点の数の平均を求めた。
課題13では、1≦x≦n, 1≦y≦n の範囲から『ランダム』に格子点を選択、原点から見えるかどうかを判定し、
原点から見える格子点の数の平均を求める。
また、x,yの定義域からも分かると思うが、本課題ではx軸、y軸上の格子点(x,y)=(1,0),(0,1)は含まない。
入力
平面のサイズ :n (1≦x,y≦n)
試行回数(ランダムに選ぶ格子点の数) :m
出力
原点から見えるランダムに選ばれた格子点の数の平均
※今回は課題3とは異なり、原点から見える格子点の数を、平面の面積n×nで割ってはいけない。
課題13では、ランダムに選ばれた m 個の格子点に含まれる原点から見える格子点の割合を求めるので、
平均は、原点から見える格子点の数を試行回数 m で割ることにより得られる 点に注意すること。
実行
nの値を「10000000」 、mの値を「1000000」 とした場合で実行し、その値を示せ。
※桁数は課題3に比べて大きくなっているが、課題3の場合、評価した格子点の数は n×n であった。
課題13における m=1000000 は、課題3における n=1000 と格子点の評価回数は同じである。
ヒント
ランダム生成
今回は乱数 の生成が必須となる。
今回初めて乱数を扱う学生もいると思われるので、乱数生成に役立つ関数を以下にまとめる。
関数
関数
引数の型
出力の型
意味
trunc(x)
Real
Integer
xの小数部を切り捨て
random(n)
Integer
Integer
乱数 r を生成(0≦r<1)
seed(n)
※下記参照
※下記参照
乱数の種を生成する
Pascalにおける関数 random(n) は、0≦r<n の乱数 r (整数)を生成する場合もあるが、
IEDの環境では、引数に関わらず 0≦r<1 の乱数 r が生成される。
生成された乱数 r を、1≦x,y≦n に拡張することができれば、今回の課題の半分以上が完成するだろう。
次に、関数 seed(n) について簡単に説明する。
seed(n) は、乱数を生成する元となる種 を生成する関数である。
seed(n) を処理せずに random(n) などで乱数を生成しても、
元となる種が変わらないために、毎回同じ値の組しか出力されない。
for i := 1 to 10 do
writeln(random(0));
上記のようなプログラムを作成し、数回実行してみれば良く分かると思う。
よって、乱数を生成する際には、seed(n) を実行する必要がある。
seed(n) の引数には、一般的に wallclock を用いる。
但し、seed(n) は関数であるため、値を出力する。
処理の都合上、何らかの変数に格納する必要がある。
var
i : integer;
begin
i := seed(wallclock);
.
.
.
これで、乱数の種は生成完了である。
種を格納した変数 i だが、これは以降の処理でどのように扱っても構わない。
例えば、下記のようにfor文で使用してしまっても問題ない。
i := seed(wallclock);
for i := 1 to n do ;
{処理}
なぜなら、seed(wallclock) が実行された段階で、乱数の種は生成されているからである。
意味も無く、変数 i に代入することに違和感を覚えるのであれば、次のようにすることも可能である。
writeln(seed(wallclock));
これでも、乱数の種は生成される。但し、当然画面上に seed(wallclock) の値が出力される。
一度、seed(wallclock) の値を出力してみるのも面白いかもしれない。