かつてのひまな野球人の記

野球が好きだった医者が書きたいことを書き散らすブログ。今は保健センター教員をしつつ神経内科医と研究者もやっています。

肝はどこにあるか

2007年01月05日 21時21分20秒 | 雑談
これは以前私が組んだプログラムの一部である。
function check(j,k:integer):boolean;
 var c : integer;
 begin
  check:= true;
  for c := k+1 to n do begin
   if j = a[c] then check := false
   else if j + c - k = a[c] then check := false
   else if j - c + k = a[c] then check := false
  end;
 end;
procedure printout;
 var c,d : integer;
 begin
  writeln(' No.',b);
  b := b+1;
  write(' ');
  for c := 1 to n do write(' ',c);
  writeln;
  for c := 1 to n do begin
   write(c);
   for d := 1 to n do begin
    if d = a[c] then write(' Q')
    else write (' ');
   end;
   writeln;
  end;
 end;
procedure put(k:integer);
 var c : integer;
 begin
  if k = 0 then printout
  else begin
   for c := 1 to n do begin
    a[k] := c;
    if check(c,k) then put(k-1);
   end;
  end;
 end;
これは「8クイーン」という問題を解くために組んだものなのだが、当の本人もだいぶ昔に組んだものなので忘れている。8クイーンとは、こういう問題である。
「チェスのクイーンを互いに利き筋に入らないように配置せよ。」
とりあえず、これらは全部サブルーチンでメインプログラムはこの後に少しだけ用意してある。しかし、機能はこの3つのサブルーチンでだいたい決まっている。このうち、printoutというのは文字通り表示するためのサブルーチンである。checkは要するに利き筋にあるかどうかを判定するための関数で、返ってくる値はtrueかfalseである。aは配列変数で、行の値に対応してクイーンのある列の値を格納する。bとnは便宜上ある整数型変数である。putはaに値を代入する部分である。再帰的にどんどん値を入れていくようになっているため、nが大きいと計算量がさらに多くなってしまうのが難点である。しかも、このプログラムでは答えは出るのだが、本質的に同じ答え(回転させたり、鏡に映したりすると重なるもの)を区別できず全部表示してしまう。そこを直す必要がある。
最近遠ざかっていたので、思い出すまでが一苦労だ。