このディレクトリの索引
#  述語 項複写/2 を定義してください。第二引数に以下のように複写された項が
#       戻されます。
#  
#       ?- 項複写(p(u,A,B,A),X).
#       X = p(u,_1,_2,_1).
#
#       A が 2つ現れるので、複写された項にも _1 が2つ必要。
#       基本的にはfunctor/3や=../2を使えば構造の複写はできるのですが、
#       最終的に第一引数に現れる共通する変数の関係を第二引数の項に
#       反映しなくてはなりません。
#       これをどうやって定義するか?  

% *** user: 項複写 / 6 ***

項複写(M,N,P,P1,VarList,VarList) :-
        M > N,!.
項複写(M,N,P,P1,VarList1,VarList2) :-
        arg(M,P,T),
        arg(M,P1,T1),
        項複写(T,T1,VarList1,VarList3),
        M1 is M + 1,
        項複写(M1,N,P,P1,VarList3,VarList2),!.

% *** user: 項複写 / 4 ***

項複写(P,P1,VarList1,VarList2) :-
        struct(P),
        functor(P,F,A),
        functor(P1,F,A),
        項複写(1,A,P,P1,VarList1,VarList2),!.
項複写(P,P1,VarList1,[(P,P1)|Varlist2]) :-
        var(P),
        変数リストの更新(P,P1,VarList1,VarList2),!.
項複写(P,P1,VarList,VarList) :-
        \+(var(P)),
        atom_to_term(P,Q,_),
        \+(P == Q),
        sprintf(%q,[P],P1),!.
項複写(P,P,Varlist,VarList).

% *** user: 項複写 / 2 ***

項複写(_項1,_項2) :-
        項複写(_項1,_項2,[],VarList),!.

% *** user: 変数リストの更新 / 4 ***

変数リストの更新(P1,P2,[],[]) :- !.
変数リストの更新(P1,P2,[(V1,V2)|R3],[(V1,P2)|R4]) :-
        V1 == P1,
        V2 = P2,
        変数リストの更新(P1,P2,R3,R4),!.
変数リストの更新(P1,P2,[(V1,V2)|R3],[(V1,V2)|R4]) :-
        \+(V1 == P1),
        変数リストの更新(P1,P2,R3,R4),!.