こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

ラテン方格での順列作成

fortranでラテン方格を作るプログラムを作っていますが、
4 3 2 1
1 2 3 4
2 1 3 4
1 4 2 3
と縦方向で同じ数字を繰り返してしまいます。必要なのは
4 3 2 1
1 2 3 4
2 1 4 3
3 4 1 2
です。参考に現時点でのプログラムをプログラムは以下のとおりです。最終的には100×100ぐらいを作りたいと思っています。

INTEGER :: K
INTEGER, DIMENSION(4) ::T
READ (*,*) N
DO 500 NN=1,N
T(NN)=NN
500 CONTINUE
write (*,'(1X,5I3)') T
OPEN(UNIT=9,FILE='outmt')
DO 505 NTB=1,4
DO 504 I=1,N
S=rand()
K=(S*I)+1
TMP = T(K)
T(K) = T(I)
T(I) = TMP
504 CONTINUE
write (9,'(1X,4I3)') T
505 CONTINUE
END

投稿日時 - 2008-05-10 12:53:58

QNo.4011313

すぐに回答ほしいです

質問者が選んだベストアンサー

ANo.1の指摘どおり,縦方向にすでに登場している数字かどうかを判定する必要がありますから,1次元配列ではなく2次元配列を用いることになるでしょう。

しかし,乱数を使って数字を1つ当てはめた後それが規則に合っているか検査していく,なんて複雑ですよ。ja.Wikipediaによると,

ラテン方格は、第1行および第1列が自然な順序で並んでいる場合に標準形という。
どんなラテン方格も行、または列を交換することで標準形にできる。
http://ja.wikipedia.org/wiki/ラテン方格

ということですから,
規則正しい標準形のラテン方陣をまず作っておいて,あとは乱数で行・列を決めて好きな回数だけ交換するのが良いのではないですか。全面全色そろったルービックキューブを先に用意しておき,好きな回数だけ行・列をランダムに崩していくイメージです。

FORTRANの実効環境が手元にないので,ある別のプログラム言語で,4×4の2次元配列中に規則正しい標準形のラテン方陣を作り出すコードを書いてみました。コード中の % は剰余演算子です。
----------------------------------------
$n = 4;
foreach $i (1..4) {
 $nn = $i;
 foreach $j (1..4) {
  $t[$i][$j] = $nn;
  $nn = ($nn % $n) + 1;
 }
}
foreach $i (1..4) {
 foreach $j (1..4) {
  print $t[$i][$j], " ";
 }
 print "\n";
}
----------------------------------------

これがどんなプログラム言語か知らなくても,アルゴリズムのイメージはつかめるのではないでしょうか。これを実行すると次のように出力されます。
------------
1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3
------------

投稿日時 - 2008-05-10 20:56:35

お礼

ご回答ありがとうございます。
ご指摘のとおり1行目に標準型を一度作ってそこからランダムにして、縦方向は1行ずれる毎に1列ずらすということで縦方向の重複がないようにすることとしました。
具体的なプログラムまで書いていただきありがとうございました。
大変参考になりました。

投稿日時 - 2008-05-11 08:25:18

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

> 縦方向で同じ数字を繰り返してしまいます。

縦方向にすでに登場しているかどうかの判定をしないまま、
無条件に配列要素を入れ替えているところに問題があると思います。

投稿日時 - 2008-05-10 13:33:28

お礼

ご回答ありがとうございます。
ご指摘のとおり縦方向の判定をしておりませんでした。
判定をしないでよい仕組みを考えます。

投稿日時 - 2008-05-11 08:21:47

あなたにオススメの質問