このディレクトリの索引
http://toro.2ch.net/test/read.cgi/tech/1354070278/611
#  [1] 授業単元: C言語プログラミング 
#  [2] 問題文(含コード&リンク):となりどおしの数字の差がその下の数字となるように、 
#  1から15までの数を1回だけ使って例に従ってマスにいれなさい。 
#  

:- dynamic(重複が存在しない減算表/4).

重複が存在しない減算表の定義(_重複しない数ならび) :-
        重複が存在しない減算表候補の選定(_重複しない数ならび,A,B,C),
        assertz((重複が存在しない減算表(L,A,B,C) :- 'A,B,Cは高々一個'(L,A,B,C))),
        fail.
重複が存在しない減算表の定義(_).

重複が存在しない減算表候補の選定(_重複しない数ならび,A,B,C) :-
        最大値(_重複しない数ならび,_最大値),
        member(A,_重複しない数ならび),
        member(B,_重複しない数ならび),
        C is abs(A - B),
        'A,B,Cは一意であり、Cは最大値より小さい'(_最大値,A,B,C).

最大値(L,_最大値) :-
        max_list(L,_最大値).

'A,B,Cは一意であり、Cは最大値より小さい'(_最大値,A,B,C) :-
        \+(A=B),
        C < _最大値,
        \+(C=B),
        \+(C=A).

'定義::数を一回だけ使ってマスに入れる'(LL) :-
        flatten(LL,L),
        '条件生成::数を一回だけ使ってマスに入れる'(L,LL,Q),
        assertz(('数を一回だけ使ってマスに入れる'(L) :- Q)).

'条件生成::数を一回だけ使ってマスに入れる'(L,[[_上左,_上右,_下]],重複が存在しない減算表(L,_上左,_上右,_下)) :- !.
'条件生成::数を一回だけ使ってマスに入れる'(L,[[_上左,_上右,_下]|R],(重複が存在しない減算表(L,_上左,_上右,_下),P)) :-
        '条件生成::数を一回だけ使ってマスに入れる'(L,R,P).

'A,B,Cは高々一個'(L,A,B,C) :-
        '2個以上存在する'(A,0,L),!,fail.
'A,B,Cは高々一個'(L,A,B,C) :-
        '2個以上存在する'(B,0,L),!,fail.
'A,B,Cは高々一個'(L,A,B,C) :-
        '2個以上存在する'(C,0,L),!,fail.
'A,B,Cは高々一個'(L,A,B,C).

'2個以上存在する'(_,N,_) :-
        N > 1,!.
'2個以上存在する'(_,_,[]) :- !,fail.
'2個以上存在する'(C,N,[V|R]) :-
        var(V),
        '2個以上存在する'(C,N,R),!.
'2個以上存在する'(C,N,[V|R]) :-
        \+(var(V)),
        C = V,
        N_2 is N + 1,
        '2個以上存在する'(C,N_2,R),!.
'2個以上存在する'(C,N,[V|R]) :-
        \+(var(V)),
        \+(C=V),
        '2個以上存在する'(C,N,R).

?- 重複が存在しない減算表の定義([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]).

?- 数を一回だけ使ってマスに入れる'([[_1_1,_1_2,_2_1],[_1_2,_1_3,_2_2],[_1_3,1_4,_2_3],[_1_4,_1_5,_2_4],[_2_1,_2_2,_3_1],[_2_2,_2_3,_3_2],[_2_3,_2_4,_3_3],[_3_1,_3_2,_4_1],[_3_2,_3_3,_4_2],[_4_1,_4_2,_5_1]]).