このディレクトリの索引
http://pc12.2ch.net/test/read.cgi/tech/1260532772/487

[1] 授業単元:計算機入門及び演習 
#  [2] 問題文(含コード&リンク):http://ime.nu/kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10311.txt 
#  
#  以下の問題を解くプログラムをC言語を用いて作成しなさい. 
#  
#  AさんとBさんは点数が書かれたカードを何枚か持っている. Aさんのカードと
#  Bさんのカードを1枚ずつ交換して,Aさんの持つカードの合計点数とBさんの持つ
#  カード合計点数が等しくなるようにしたい.
#  このときどのカードとどのカードを交換したらよいか.ただし,カードを
#  交換しなくても合計点数が等しい場合でも,必ずカードの交換を行うものとする. 
#  
#  入力は,いくつかのデータセットからなる.各データセットは次の形式で与えられる. n m
#  s1
#  s2
#  ...
#  sn
#  sn+1
#  sn+2
#  ...
#  sn+m
#  各データセットの最初の行は空白ひとつで区切られたふたつの数 n と m を含み,
#   n はAさんのカードの枚数,m はBさんのカードの枚数を表す.続く n+m 行には,
#  各カードの点数が 1 行にひとつずつ並ぶ.
#  最初の n 個の点数 (s1 から sn まで) はAさんのカードの点数,残りの
#   m 個の点数 (sn+1 から sn+m まで) はBさんのカードの点数を表す.
#   n および m は 100 以下の正の整数とし,カードの点数は 0 以上 100 以下の
#  整数値とする.入力の終わりは,空白ひとつで区切られたふたつの 0 を含む
#  1 行で示される. 
#  各データセットに対し,Aさん,Bさんの交換前のすべてのカードと交換すべき2つの
#  カードを出力すること.形式は特に問わない(実行例を参考にすること).
#  なお,合計を等しくするようなカードの交換の方法が複数ある場合は,
#  交換するカードの点数の和が最小となるもののみを出力すること.
#  また,カードの点数の合計を等しくするような交換が存在しない場合はその旨を
#  出力すること. 
#  

'AさんとBさんは点数が書かれたカードを何枚か持っている. AさんのカードとBさんのカードを1枚ずつ交換して,Aさんの持つカードの合計点数とBさんの持つカード合計点数が等しくなるようにする'(LA,LB,LX) :-
        quicksort(LA,LA1),
        quicksort(LB,LB1),
        length(LA1,LenA),
        length(LB1,LenB),
        append(LA1,LB1,L),
        findall([L1,L2],(
                    組合せ(L,LenA,L1),
                    sum(L1,Sum),
                    'L1分をLから取り除く'(L1,L,L3),
                    組合せ(L3,LenB,L2),sum(L2,Sum)),
                LX),
        最短手順を探る(LA1,LX,_交換候補).

'L1分をLから取り除く'([],L,L) :- !.
'L1分をLから取り除く'([A|R1],L1,L2) :-
        'AをL1から取り除く'(A,L1,L3),
        'L1分をLから取り除く'(R1,L3,L2).

'AをL1から取り除く'(A,L1,L2) :-
        append(L0,[A|R],L1),
        append(L0,R,L2),!.

sum([],0) :- !.
sum([A|R],X) :-
        sum(R,Y),
        X is A + Y.

最短手順を探る(LA1,LL,_放出,_受け取り) :-
        findall([_放出,_受取],(
                    append(_,[[L1,_]|_],LL),
                    交換候補(LA1,L1,_放出,_受取)),
               LX),
        findmin(Len,(
                        append(_,[[U1,U2]|_],LX),
                        length(U1,Len)),
                Min),
        append(_,[[_放出,_受け取り]|_],LX),
        length(U1,Min).

交換候補([],L,[],L) :- !.
交換候補(L,[],L,[]) :- !.
交換候補([A|R1],[A|R2],R3,R4) :-
        交換候補(R1,R2,R3,R4),!. 
交換候補([A|R1],[B|R2],[A|R3],R4) :-
        A < B,
        交換候補(R1,[B|R2],R3,R4),!.
交換候補([A|R1],[B|R2],R3,[B|R4]) :-
        A > B,
        交換候補([A|R1],R2,R3,R4),!.