このディレクトリの索引

http://pc12.2ch.net/test/read.cgi/tech/1250204272/416
#  【質問テンプレ】 
#  [1] 二次元配列 
#  [2] 問題文:http://ime.nu/kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/9944.txt
# 二次元配列 奇数偶数 魔方陣
# 入力した数字の法人に対して1〜11までの値をある法則通りに格納し、
# 縦横斜めどのれつの合計値もすべて同じになる奇数魔方陣を作成する。
# ただし以下のことを法則とする。
# 奇数魔方陣の作り方
# 初期値(1)は真ん中の列の最上位置に格納すること。
# 数値は1ずつ加算する。加算ごとに右上に格納する
# 右側へはみ出した場合、はみ出した行の最左端セルへいく
# 上にはみ出した場合、はみ出した同列の最下位セルにいく
# 格納するセルがすでに埋まっていた場合ははみ出したセルの一つしたに格納する
# 下側にはみだしたらはみ出した列の最上位セルへいく
# ・偶数魔方陣も作成すること (法則はネットに書いてあるのでいいっぽいです。対角線上のやつ?)
# ・12以上の数字が入力された場合は再入力を求める。

奇数魔方陣(_サイズ,_魔方陣行列) :-
    奇数(_サイズ),
    X起点 is _サイズ // 2 + 1,
    変数正方行列の生成(_サイズ,_魔方陣行列),
    変数正方行列を埋めていく(1,_サイズ,X起点,1,_魔方陣行列).

変数正方行列の生成(_サイズ,_変数正方行列) :-
    findall(L1,(for(1,N,_サイズ),findall(U,length(U,_サイズ),L1)),_変数正方行列),!.

変数正方行列を埋めていく(M,_サイズ,_,_,_魔方陣行列) :-
    M > _サイズ * _サイズ,!.
変数正方行列を埋めていく(M,_サイズ,X1,Y1,_魔方陣行列) :-
    X1 >= 1,X1 =< _サイズ,Y1 >= 1,Y1 =< _サイズ,
    \+(はみ出したセルの一つ下にいく(_サイズ,_魔方陣行列,X1,Y1,X,Y)),
    行列変数に値を入れる(X1,Y1,M,_魔方陣行列),
    斜め上方に移動(X1,Y1,X2,Y2),
    M2 is M + 1,
    変数正方行列を埋めていく(M2,_サイズ,X2,Y2,_魔方陣行列).
変数正方行列を埋めていく(M,_サイズ,X1,Y1,_魔方陣行列) :-
    X1 >= 1,X1 =< _サイズ,Y1 >= 1,Y1 =< _サイズ,
    はみ出したセルの一つ下にいく(_サイズ,_魔方陣行列,X1,Y1,X2,Y2),
    変数正方行列を埋めていく(M,_サイズ,X2,Y2,_魔方陣行列).
変数正方行列を埋めていく(M,_サイズ,_魔方陣行列) :-
    はみ出した行の最左端セルへいく(_サイズ,X1,Y1,X2,Y2),
    変数正方行列を埋めていく(M,_サイズ,X2,Y2,_魔方陣行列),!.
変数正方行列を埋めていく(M,_サイズ,X1,Y1,_魔方陣行列) :-
    はみ出した同列の最上位セルにいく(_サイズ,X1,Y1,X2,Y2),
    変数正方行列を埋めていく(M,_サイズ,X2,Y2,_魔方陣行列),!.
変数正方行列を埋めていく(M,_サイズ,_魔方陣行列) :-
    はみ出した同列の最下位セルにいく(_サイズ,X1,Y1,X2,Y2),
    変数正方行列を埋めていく(M,_サイズ,X2,Y2,_魔方陣行列),!.


はみ出したセルの一つ下にいく(_サイズ,_魔方陣行列,X1,Y1,X1,Y2) :-
    格納するセルがすでに埋まっていた場合(_サイズ,_魔方陣行列,X1,Y1),
    Y2 is Y1 + 1,!.
    
格納するセルがすでに埋まっていた場合(_サイズ,X1,Y1,_魔方陣行列) :-
    list_nth(Y1,_魔方陣行列,_行),
    list_nth(X1,_行,V),
    \+(var(V)),!.

はみ出した行の最左端セルへいく(_サイズ,X1,Y1,1,Y1) :-
    右側へはみ出した場合(_サイズ,X1,Y1),!.
はみ出した同列の最下位セルにいく(_サイズ,X1,Y1,X1,_サイズ) :-
    上側にはみ出した場合(_サイズ,X1,Y1),!.
はみ出した列の最上位セルへいく(_サイズ,X1,Y1,X1,1) :-
    下側にはみ出した場合(_サイズ,X1,Y1).

右側へはみ出した場合(_サイズ,X,Y) :-
    X > _サイズ,!.
上側にはみ出した場合(_サイズ,X,0) :- !.
下側にはみ出した場合(_サイズ,X,Y) :-
    Y > _サイズ,!.

行列変数に値を入れる(X1,Y1,M,_魔方陣行列) :-
    list_nth(Y1,_魔方陣行列,_行),
    list_nth(X1,_行,M),!.

斜め上方に移動(X1,Y1,X2,Y2) :-
    X2 is X1 + 1,
    Y2 is Y1 - 1.

奇数(N) :- 1 is N mod 2.