このディレクトリの索引
http://pc12.2ch.net/test/read.cgi/tech/1263824755/420
#  [1] 授業単元:プログラミング実践  
#  [2] 問題文 
#  アフィン変換のプログラムを作成し、下の図の真ん中を座標の中心にして90°回転した結果を出力せよ。  
#  (図)affin.txt 
#  00000 
#  00000 
#  11111 
#  00000 
#  00000 
#   
#  

アフィン変換により原点を中心に90度回転(X1,X2,Y1,Y2,_行列1,_アフィン変換された行列) :-
        length(_行列1,Len1),
        nth1(1,_行列1,_行),
        length(_行,Len2),
        findall([XX2,YY2,V],アフィン変換により原点を中心に90度回転(X1,X2,Y1,Y2,_行列1,XX2,YY2,V),L1),
        アフィン変換_2(1,Len1,1,Len2,L1,_アフィン変換された行列).

アフィン変換により原点を中心に90度回転(X1,X2,Y1,Y2,_行列1,XX2,YY2,V) :-
        between(X1,X2,X),
        between(Y1,Y2,Y),
        行列の掛算([[0,1,0],[-1,0,0]],[[X],[Y],[1]],[[X3],[Y3]]),
        XX is X + 3,
        YY is Y + 3,
        XX2 is X3 + 3,
        YY2 is Y3 + 3,
        nth1(YY,_行列1,_行1),
        nth1(XX,_行1,V).

アフィン変換_2(M,Len1,_,_,_,[]) :-
        M > Len1,!.
アフィン変換_2(M,Len1,N,Len2,L,[[]|R2]) :-
        N > Len2,
        M2 is M + 1,
        アフィン変換_2(M2,Len1,N,1,L,R2),!.
アフィン変換_2(M,Len1,N,Len2,L,[[V|R1]|R2]) :-
        N =< Len2,
        member([M,N,V],L),
        N2 is N + 1,
        アフィン変換_2(M,Len1,N2,Len2,L,[R1|R2]),!.
アフィン変換_2(M,Len1,N,Len2,L,[[0|R1]|R2]) :-
        N =< Len2,
        \+(member([M,N,V],L)),
        N2 is N + 1,
        アフィン変換_2(M,Len1,N2,Len2,L,[R1|R2]),!.

行列の掛算(L1,L2,X) :-
    転置(L2,L4),
    行列の掛算_1(L1,L4,X).

行列の掛算_1([],_,[]) :- !.
行列の掛算_1([A|R1],L,[S1|R3]) :-
    行列の掛算_2(A,L,S1),
    行列の掛算_1(R1,L,R3).

行列の掛算_2(_,[],[]) :- !.
行列の掛算_2(A,[B|R2],[C|R3]) :-
    行列の掛算_3(A,B,C),
    行列の掛算_2(A,R2,R3).

行列の掛算_3([],[],0) :- !.
行列の掛算_3([A|R1],[B|R2],S) :-
    分数を含む掛算(A,B,S1),
    行列の掛算_3(R1,R2,S2),
    分数を含む加算(S1,S2,S),!.

分数を含む掛算(A1 / A2,B1 / B2,C) :-
    S1 is A1 * B1,
    S2 is A2 * B2,
    約分(S1 / S2,C),!.
分数を含む掛算(A1 / A2,B,C) :-
    S1 is A1 * B,
    約分(S1 / A2,C),!.
分数を含む掛算(A,B1 / B2,C) :-
    S1 is B1 * A,
    約分(S1 / B2,C),!.
分数を含む掛算(A,B,C) :-
    C is A * B.

分数を含む加算(A,B,C) :-
    number(A),
    number(B),
    C is A + B,!.
分数を含む加算(A1 / B1,A2 / B2,C) :-
    A3 is A1 * B2 + A2 * B1,
    B3 is B1 * B2,
    約分(A3 / B3,C),!.
分数を含む加算(A1 / B1,V,C) :-
    number(V),
    A2 is V * B1,
    C3 is A1 + A2,
    約分(C3 / B1,C),!.
分数を含む加算(V,A2 / B2,C) :-
    number(V),
    A1 is V * B2,
    C3 is A1 + A2,
    約分(C3 / B2,C),!.

約分(B / A,X) :-
    最大公約数(B,A,C),
    _分子 is B // C,
    _分母 is A // C,
    約分の二(_分子,_分母,X),!.

約分の二(_分子,1,_分子) :- !.
約分の二(_分子,1.0,_分子) :- !.
約分の二(_分子_1,_分母_1,_分子 / _分母) :-
    分母が負数だったら分子分母ともに符号を反転する(_分子_1,_分母_1,_分子,_分母),!.
約分の二(_分子,_分母,_分子 / _分母).


転置([],[],[]) :- !.
転置([[A|R1]|R2],[R1|R3],[A|R4]) :-
    転置(R2,R3,R4) .

転置([[]|_],[]) :- !.
転置(L,[L1|R2]) :-
    転置(L,L2,L1),
    転置(L2,R2).


?- アフィン変換により原点を中心に90度回転(-2,2,-2,2,[[0,0,0,0,0],[0,0,0,0,0],[1,1,1,1,1],[0,0,0,0,0],[0,0,0,0,0]],L).