このディレクトリの索引

http://pc12.2ch.net/test/read.cgi/tech/1247438792/157 
# [1] 授業単元: C++ 
# [2] 問題文(含コード&リンク): 
# http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/9762.txt 
# 
# 正数による正方行列のうち、全ての行、列、斜め列の合計が同じであり、 
# かつ2回以上使用される数字が存在しないものを魔方陣という。 
# 下図に示すa,bに数値を設定したときに、1〜9の整数によって構成される魔方陣を 
# 出力するプログラムを作成せよ。 
# 但し、魔方陣が作成不可能な(a,b)の組み合わせが設定された場合は、「Impossible」 
# と出力するとする。 
# 
# la_lb_l__l 
# l__l__l__l 
# l__l__l__l 
# 

魔方陣(N枡,A,B,_行列) :-
    魔方陣のための行列の生成(N枡,_行列),
    _行列 = [[A,B|_],_,_],
    行の合計が全て一致する(_行列,S),
    列の合計が全て一致する(_行列,S),
    正方行列の斜め要素の合計が一致する(_行列,S).

魔方陣のための行列の生成(N枡,_行列) :-
    N2 is N枡 ^ 2,
    findall(M,for(1,M,N2),NL),!,
    順列(NL,N2,_順列数字ならび),
    findall(_N個組,n個組(N枡,_順列数字ならび,_N個組),_行列).

行の合計が全て一致する([],S) :- !.
行の合計が全て一致する([_行|R],S) :-
    魔方陣の加算(_行,0,S),
    行の合計が全て一致する(R,S).

列の合計が全て一致する(_行列,S) :-
    行列の転置(_行列,_転置行列),
    列の合計が全て一致する(_転置行列,S),!.

正方行列の斜め要素の合計が一致する(_正方行列,S) :-
    length(_行列,Len),
    左上から右下方向の合計(1,Len,_正方行列,0,S),
    右上から左下方向の合計(1,Len,_正方行列,0,S),!.

左上から右下方向の合計(M,N,_,S,S) :- M > N,!.
左上から右下方向の合計(M,N,_行列,S1,S) :-
    list_nth(M,_行列,_行),
    list_nth(M,_行,_要素),
    S2 is _要素 + S1,
    M2 is M + 1,
    左上から右下方向の合計(M2,N,_行列,S2,S),!.

右上から左下方向の合計(M,N,_,S,S) :- M > N,!.
右上から左下方向の合計(M,N,_行列,S1,S) :-
    M1 is N - M + 1,
    list_nth(M1,_行列,_行),
    list_nth(M1,_行,_要素),
    S2 is _要素 + S1,
    M2 is M + 1,
    右上から左下方向の合計(M2,N,_行列,S2,S),!.

n個組(N,L,X) :-
    length(X,N),
    append(X,L2,L3),
    append(L1,L3,L),
    length(L1,Len),
    0 is Len mod N.

魔方陣の加算([],X,X) :- !.
魔方陣の加算([A|R],Y,X) :-
    Z is A + Y,
    魔方陣の加算(R,Z,X).