(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(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) の値を出力してみるのも面白いかもしれない。