このディレクトリの索引
http://pc12.2ch.net/test/read.cgi/tech/1260532772/388
#  [1] 授業単元:計算機入門及び演習
#  [2] 問題文(含コード&リンク):http://ime.nu/ime.nu/kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10300.txt
# http://ime.nu/prolog.asia/txt/10300.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つのカードを出力すること.形式は特に問わない(実行例を参考にすること).なお,合計を等しくするようなカードの交換の方法が複数ある場合は,交換するカードの点数の和が最小となるもののみを出力すること.また,カードの点数の合計を等しくするような交換が存在しない場合はその旨を出力すること. 
# 
# 実行例
# 
# 
# nodat000% cat ~j-teru/sample-input.txt
# 2 2
# 1
# 5
# 3
# 7
# 6 5
# 3
# 9
# 5
# 2
# 3
# 3
# 12
# 2
# 7
# 3
# 5
# 4 5
# 10
# 0
# 3
# 8
# 1
# 9
# 6
# 0
# 6
# 7 4
# 1
# 1
# 2
# 1
# 2
# 1
# 4
# 2
# 3
# 4
# 3
# 2 3
# 1
# 1
# 2
# 2
# 2
# 2 2
# 5
# 1
# 7
# 3
# 0 0
# nodat000% ./cardchange < ~j-teru/sample-input.txt
# Aさんのカード: 1 5 
# Bさんのカード: 3 7 
# Aさんの1とBさんの3を交換
# 
# Aさんのカード: 3 9 5 2 3 3 
# Bさんのカード: 12 2 7 3 5 
# Aさんの3とBさんの5を交換
# 
# Aさんのカード: 10 0 3 8 
# Bさんのカード: 1 9 6 0 6 
# 合計を等しくする交換はありません
# 
# Aさんのカード: 1 1 2 1 2 1 4 
# Bさんのカード: 2 3 4 3 
# Aさんの2とBさんの2を交換
# 
# Aさんのカード: 1 1 
# Bさんのカード: 2 2 2 
# 合計を等しくする交換はありません
# 
# Aさんのカード: 5 1 
# Bさんのカード: 7 3 
# Aさんの1とBさんの3を交換
# 
# nodat000% 

入力したデータセットを一枚交換して合計が一致する組をすべて示す(AL,BL,A,B) :-
    データセットの入力(N,M,AL,BL),
    一枚ずつ全てを交換してみる(N,M,AL,BL,A,B).

データセットの入力(N,M,AL,BL) :- get_split_line([' '],[N,M]),\+((N=0,M=0)),'Aの入力'(N,AL),'Bの入力'(M,BL),!.

'Aの入力'(N,AL) :- findall(A,(for(1,_,N),get_integer(A)),AL).
'Bの入力'(M,AL) :- findall(B,(for(1,_,M),get_integer(B)),BL).

一枚ずつ全てを交換してみる(0,M,AL,BL,_,_) :- !,fail.
一枚ずつ全てを交換してみる(N,M,AL,BL,A,B) :-
    ならびの回転(左方向,1,AL,[A|R1]),
    交換して合計が一致する(M,BL,A,B).
一枚ずつ全てを交換してみる(N,M,AL,BL,A,B) :-
    ならびの回転(左方向,1,AL,AL2),
    N1 is N - 1,
    一枚ずつ全てを交換してみる(N1,M,AL2,BL,A,B).

交換して合計が一致する(0,[A|R1],[B|R2],A,B) :- !,fail.
交換して合計が一致する(M,[A|R1],[B|R2],A,B) :- sum([B|R1],Sum), sum([A|R2],Sum).
交換して合計が一致する(M,[A|R1],[B|R2],A,B) :-
    ならびの回転(左方向,1,BL,BL2),
    M1 is M - 1,
    交換して合計が一致する(M1,[A|R1],BL2,A,B).