このディレクトリの索引
http://pc12.2ch.net/test/read.cgi/tech/1276810079/335
#  [1] 授業単元:プログラミング演習 
#  [2] 問題文(含コード&リンク):ファイルに保存された会員情報を指定された項目をキーとしてソートするプログラムを作成する. 
#  出力形式は,入力データと同じ,つまり1行に1人分のデータを格納し,各項目間はカンマで区切るものとする. 
#  また,ソート済みのデータはファイルではなく標準出力に出力するものとする. 
#  整数型のデータについては数値として,文字列型のデータについては大文字/小文字を区別せずにソートをすること. 
#  ソートアルゴリズムはこれまでの演習で使用したもの,していないものに関わらず,何を用いてもよい. 
#   
#  また,会員数は最大で20,000人と仮定してもよい. 
#   
#  会員情報の入ったファイルのファイル名,キーとなる項目,正順か逆順かの指定はプログラム実行時の引数として与える.第一引数が会員情報の入ったファイル名,第二引数が項目番号(表1参照),第三引数がソート方法(0なら昇順,1なら降順)とする.  
#   
#  表1: データ型 項目名 項目番号 型 
#  会員ID 1 整数(int) 
#  姓 2 文字列(最大で50文字) 
#  名 3 文字列(最大で50文字) 
#  年齢 4 整数(int) 
#  州 5 文字列(最大で50文字) 
#  郡 6 文字列(最大で50文字) 
#   
#   
#  

オンメモリ整列限界数(1000).

ファイルに保存された会員情報を指定された項目をキーとしてソートする(_対象ファイル,_鍵項目番号,_ソート方法) :-
        オンメモリ整列限界数(_オンメモリ整列限界数),
        open(_対象ファイル,read,Input),
        ふたつの仮ファイルの取得と交互からくり生成,
        入力出力ファイルを交互しながらの繰り返し(_,_仮出力ファイル,InputT,OutputT),
        対象ファイルから読み込む(Input,_オンメモリ整列限界数,_鍵項目番号,LL,_診断),
        昇降順・指定整列(LL,_ソート方法,_整列されたLL),
        鍵項目番号とソート方法をしてファイルマージ(_整列されたLL,_ソート方法,InputT,OutputT),
        \+(_診断=1000),close(Input),
        仮出力ファイルの内容を整理しながら標準出力に表示する(_仮出力ファイル).

入力出力ファイルを交互しながらの繰り返し(_仮ファイルA,_仮ファイルB,InputT,OutputT) :-
        仮ファイルからくり(_仮ファイルA,_仮ファイルB),
        open(_仮ファイルA,read,InputT),
        open(_仮ファイルB,write,OutputT).

仮ファイルからくり(X) :- 仮ファイルからくり(X).

ふたつの仮ファイルの取得と交互からくり生成 :-
        tmpnam(_仮ファイル1),open(_仮ファイル1,write,Output1),close(Output1),
        tmpnam(_仮ファイル2),opene(_仮ファイル2,write,Output2),close(Output2),
        asserta(仮ファイルからくり(_仮ファイル2,_仮ファイル1)),
        asserta(仮ファイルからくり(_仮ファイル1,_仮ファイル2)).

対象ファイルから読み込む(Input,_オンメモリ整列限界数,_鍵項目番号,LL,_診断) :-
        対象ファイルから読み込む(Input,0,_オンメモリ整列限界数,_鍵項目番号,LL,_診断),!.

対象ファイルから読み込む(Input,_オンメモリ整列限界数,_オンメモリ整列限界数,_,[],_オンメモリ整列限界数) :- !.
対象ファイルから読み込む(Input,N,_オンメモリ整列限界数,_鍵項目番号,[[_鍵_1,_会員ID,_姓_1,_名_1,_年齢,_州_1,_郡_1]|R],_診断) :-
        get_line(Input,Line),
        N2 is N + 1,
        split([','],Line,[_会員ID,_姓,_名,_年齢,_州,_郡]),
        to_upper([_姓,_名,_州,_郡],[_姓_1,_名_1,_州_1,_郡_1]),
        list_nth(_鍵項目番号,[_会員ID,_姓_1,_名_1,_年齢,_州_1,_郡_1],_鍵),
        文字項目なら大文字に変換(_鍵,_鍵項目番号,_鍵_1),
        対象ファイルから読み込む(Input,N,_オンメモリ整列限界数,_鍵項目番号,R,_診断).

文字項目なら大文字に変換(_鍵,_鍵項目番号,_鍵_1) :-
        member(_鍵項目番号,[2,3,5,6]),
        to_upper(_鍵,_鍵_1),!.
文字項目なら大文字に変換(_鍵,_,_鍵).

昇降順・指定整列(LL,1,_整列されたLL) :- sort(LL,_整列されたLL).
昇降順・指定整列(LL,2,_整列されたLL) :- rsort(LL,_整列されたLL).

鍵項目番号とソート方法をしてファイルマージ([],end_of_file,_,InputT,OutputT) :- !.
鍵項目番号とソート方法をしてファイルマージ([L1|R1],end_of_file,_,InputT,OutputT) :-
        write_formatted(OutputT,'%t,%t,%t,%t,%t,%t,%t\n',L1),
        鍵項目番号とソート方法をしてファイルマージ(R1,end_of_file,_,InputT,OutputT),!.
鍵項目番号とソート方法をしてファイルマージ([],[_鍵2|L2],_,InputT,OutputT) :-
        write_formatted(OutputT,'%t,%t,%t,%t,%t,%t,%t\n',[_鍵2|L2]),
        eofまでコピーする(InputT,OutputT),
        close(InputT),
        close(OutputT),!.
鍵項目番号とソート方法をしてファイルマージ([[_鍵1|L1]]|R1],[_鍵2|L2],1,InputT,OutputT) :-
        _鍵1 @=< _鍵2,
        write_formatted(OutputT,'%t\n',[_鍵1|L1]),
        鍵項目番号とソート方法をしてファイルマージ(R1,[_鍵2|L2],_ソート方法,InputT,OutputT).
鍵項目番号とソート方法をしてファイルマージ([[_鍵1|L1]|R1],[_鍵2|L2],1,InputT,OutputT) :-        
        _鍵1 @> _鍵2,
        write_formatted(OutputT,'%t\n',[_鍵2|L2]),
        get_line(InputT,Line),
        atom_to_term(Line,(_鍵3,_会員ID3,_姓3,_名3,_年齢3,_州3,_郡3),_),
        鍵項目番号とソート方法をしてファイルマージ(R1,[_鍵3,_会員ID3,_姓3,_名3,_年齢3,_州3,_郡3],_ソート方法,InputT,OutputT).
鍵項目番号とソート方法をしてファイルマージ([[_鍵1|L1]|R1],[_鍵2|L2],2,InputT,OutputT) :-
        _鍵1 @>= _鍵2,
        write_formatted(OutputT,'%t\n',[_鍵1|L1]),
        鍵項目番号とソート方法をしてファイルマージ(R1,[_鍵2|L2],_ソート方法,InputT,OutputT).
鍵項目番号とソート方法をしてファイルマージ([[_鍵1|L1]|R1],[_鍵2|L2],2,InputT,OutputT) :-        
        _鍵1 @< _鍵2,
        write_formatted(OutputT,'%t\n',[_鍵2|L2]),
        get_line(InputT,Line),
        atom_to_term(Line,(_鍵3,_会員ID3,_姓3,_名3,_年齢3,_州3,_郡3),_),
        鍵項目番号とソート方法をしてファイルマージ(R1,[_鍵3,_会員ID3,_姓3,_名3,_年齢3,_州3,_郡3],_ソート方法,InputT,OutputT).

eofまでコピーする(InputT,OutputT) :-
        repeat,
        get_line(Line),
        (   Line=end_of_file;write_formatted('%t\n',[Line]),fail),!.

仮出力ファイルの内容を整理しながら標準出力に表示する(_仮出力ファイル) :-
        open(_仮出力ファイル,read,Input),
        repeat,
        get_line(Line),
        (   Line=end_of_file;
            split([','],Line,[_|L]),
            write_formatted('%t,%t,%t,%t,%t,%t\n',L),
            fail
        ).