このディレクトリの索引
http://hibari.2ch.net/test/read.cgi/tech/1311089619/570
#  [2] 問題文(含コード&リンク): 以下の性能を持つ名簿プログラムを作成せよ 
#  氏名、年齢、住所、電話番号、メールアドレス、郵便番号を持つ構造体を使用する 
#  一覧を表示可能である 
#  作成したデータはファイルとして保存、読み込みができる 
#  構造体の追加、削除が可能である 
#  任意の項目を修正可能である 
#  任意の項目をキーとして検索、ソート(昇順・降順)が可能である 
#   
#  
%
%  目標として名簿述語を呼び出す場合は、failでバックトラックさせる。この場合、
%  最終的に第一節は偽となるので、真で終了させたい場合は第二節が必要。

'名簿一覧表示' 
        見出し表示,
        名簿(氏名(_氏名),年齢(_年齢),住所(_住所),電話番号(_電話番号),メールアドレス(_メールアドレス),郵便番号(_郵便番号)),
        writef('%t,%t,%t,%t,%t,%t\n',[_氏名,_年齢,_住所,_電話番号,_メールアドレス,_郵便番号]),
        fail.
'名簿一覧表示.

見出し表示 :-
        write('氏名,年齢,住所,電話番号,メールアドレス,郵便番号\n').

'作成したデータをファイルとして保存する'(_ファイル) :-
        listing(_ファイル),!.

'データをファイルから読みだして定義する'(_ファイル) :-
        consult(_ファイル).        

構造体の追加(_氏名,_年齢,_住所,_電話番号,_メールアドレス,_郵便番号) :-
        assertz(名簿(氏名(_氏名),年齢(_年齢),住所(_住所),電話番号(_電話番号),メールアドレス(_メールアドレス),郵便番号(_郵便番号)),!.

構造体の削除(_氏名,_年齢,_住所,_電話番号,_メールアドレス,_郵便番号) :-
        retract(名簿(氏名(_氏名),年齢(_年齢),住所(_住所),電話番号(_電話番号),メールアドレス(_メールアドレス),郵便番号(_郵便番号)),!.

'任意の項目を修正可能である'(_氏名,_年齢,_住所,_電話番号,_メールアドレス,_郵便番号,_修正項目名_修正値ならび) :-
        retract(名簿(氏名(_氏名),年齢(_年齢),住所(_住所),電話番号(_電話番号),メールアドレス(_メールアドレス),郵便番号(_郵便番号)),
        任意の項目の修正([氏名(_氏名),年齢(_年齢),住所(_住所),電話番号(_電話番号),メールアドレス(_メールアドレス),郵便番号(_郵便番号)],_修正項目ならび,L),
        P =.. [名簿|L],
        asserta(P).

任意の項目の修正([],_,[]) :- !.
任意の項目の修正([_項|R1],_修正項目ならび,[_項2|R2]) :-
        _項 =.. [_関数名,_値1],
        member(_項2,_修正項目ならび),
        _項2 =.. [_関数名,_値2],
        任意の項目の修正(R1,_修正項目ならび,R2),!.
任意の項目の修正([_項|R1],_修正項目ならび,[_項|R2]) :-
        任意の項目の修正(R1,_修正項目ならび,R2),!.


'任意の項目をキーとして検索、昇順ソート'(_項目名) :-
        述語定義では整列できないからキーを付加しながらならびに変換(_項目名,L1),
        昇順整列(L1,L2),
        整列したならびを述語として定義し直す(L2).

'任意の項目をキーとして検索、降順ソート'(_項目名) :-
        述語定義では整列できないからキーを付加しながらならびに変換(_項目名,L1),
        降順整列(L1,L2),
        整列したならびを述語として定義し直す(L2).

整列したならびを述語として定義し直す(L2) :-
        abolish(名簿/6),
        append(_,[[_,氏名(_氏名),年齢(_年齢),住所(_住所),電話番号(_電話番号),メールアドレス(_メールアドレス),郵便番号(_郵便番号)]|R],L2),
        assertz(名簿(氏名(_氏名),年齢(_年齢),住所(_住所),電話番号(_電話番号),メールアドレス(_メールアドレス),郵便番号(_郵便番号)),
        R = [],!.

述語定義では整列できないからキーを付加しながらならびに変換(_項目名,L1) :-
        findall([_任意項目|L],(
                    名簿(氏名(_氏名),年齢(_年齢),住所(_住所),電話番号(_電話番号),メールアドレス(_メールアドレス),郵便番号(_郵便番号)),
                    _項 =.. [_項目名,_値],
                    member(_項,[氏名(_氏名),年齢(_年齢),住所(_住所),電話番号(_電話番号),メールアドレス(_メールアドレス),郵便番号(_郵便番号)])),
                L1),!.

昇順整列([],[]) :- !.
昇順整列(L1,L2) :-
        L1 = [A|R],
        昇順整列(A,R,L2).

昇順整列(A,L1,L2) :-
        昇順分割(A,L1,_より小さいならび,_より大きいならび),
        昇順整列(_より小さいならび,L3),
        昇順整列(_より大きいならび,L4),
        append(L3,[A|L4],L2).

昇順分割(_,[],[],[]) :- !.
昇順分割(A,[B|R1],[B|R2],R3) :-
        B @=< A,
        昇順分割(A,R1,R2,R3).
昇順分割(A,[B|R1],R2,[B|R3]) :-
        B @> A,
        昇順分割(A,R1,R2,R3).

降順整列([],[]) :- !.
降順整列(L1,L2) :-
        L1 = [A|R],
        降順整列(A,R,L2).

降順整列(A,L1,L2) :-
        降順分割(A,L1,_より大きいならび,_より小さいならび),
        降順整列(_より大きいならび,L3),
        降順整列(_より小さいならび,L4),
        append(L3,[A|L4],L2).

降順分割(_,[],[],[]) :- !.
降順分割(A,[B|R1],[B|R2],R3) :-
        B @> A,
        降順分割(A,R1,R2,R3).
降順分割(A,[B|R1],R2,[B|R3]) :-
        B @=< A,
        降順分割(A,R1,R2,R3).