このディレクトリの索引
#  出題場所 :: http://toro.2ch.net/test/read.cgi/tech/1381909900/696
#  [1] 授業単元: Cプログラミング 
#  [2] 問題文(含コード&リンク): データファイル(rep_data.txt)には「学籍番号、科目A、科目B、科目Cの各点数」が 
#  順に学籍番号順に並んでいる。そのデータファイルをもとにキーボードから入力された学籍番号の 
#  学生の成績(含:3科目の合計点の順位)を表示するプログラムを作れ。 
#  探索は二分探索法を使いソートにはクイックソートを使うこと。 
#   
#  表示は以下のようにすること。 
#  Input A Student Number: 14【Enter】 
#  Ranking : #269 /*最高得点は1位とせよ.*/ 
#  Subject A : 86 
#  Subject B : 59.1 
#  Subject C : 220.42 
#  Total : 365.52 
# 
#  出題場所 :: http://toro.2ch.net/test/read.cgi/tech/1381909900/697
#  【備考】 
#  科目 A の得点は int 型,科目 B,C の得点は double 型で扱うこと. 
#  合計点が同じになる学生はいないということは既知とせよ. 
#  データの人数は 1000 人であることもわかっているとせよ. 
#  学籍番号には抜けがある.学籍番号が存在しない場合は,”No data”と表示するようにせよ. 
#  雛型 (121.c) を用いよ.main 関数は完成しているので,main 関数内で呼び出している関数を作成せよ. 
#  

'データファイル(rep_data.txt)には「学籍番号、科目A、科目B、科目Cの各点数」が
順に学籍番号順に並んでいる。そのデータファイルをもとにキーボードから入力された学籍番号の
学生の成績(含:3科目の合計点の順位)を表示するプログラムを作れ。
探索は二分探索法を使いソートにはクイックソートを使うこと。' :-
        'データファイルから学籍番号、科目A、科目B、科目Cの各点数の学生成績ならびを作る'(_学生成績ならび),
        合計得点の順位表を作る(_学生成績ならび,_合計得点の順位表),
        キーボードから入力された学籍番号の(_学籍番号),
        二分探索法を使い学生の成績を得る(Lines,_学籍番号,_学生の成績),
        '学生の成績(含:3科目の合計点の順位)を表示する'(_学籍番号,_合計得点の重複を許す降順ならび,_学生の成績).

'データファイルから学籍番号、科目A、科目B、科目Cの各点数の学生成績ならびを作る'(_学生成績ならび) :-
        get_lines('rep_data.txt',Lines),
        findall(L,(
                    member(_行,Lines),
                    split(_行,[','],L)),
                _学生成績ならび).

合計得点の順位表を作る(_学生成績ならび,_合計得点の重複要素を許す降順ならび) :-
        findall(_合計,(
                    member([_,A,B,C],_学生成績ならび),
                    _合計 is A + B + C),
                _合計得点ならび),
        重複要素を許す降順整列(_合計得点ならび,_合計得点の重複要素を許す降順ならび).

キーボードから入力された学籍番号の(_学籍番号) :- 
        整数を得る(学籍番号,_学籍番号 >= 0,_学籍番号).
キーボードから入力された学籍番号の(_学籍番号) :-
        キーボードから入力された学籍番号の(_学籍番号).

二分探索法を使い学生の成績を得る(Lines,_学籍番号,_学生の成績) :-
        length(Lines,_最大要素位置),
        二分探索法を使い学生の成績を得る(1,_最大要素位置,_最大要素位置,Lines,_学籍番号,_学生の成績).

二分探索法を使い学生の成績を得る(_要素位置,_要素位置,Lines,_学籍番号,_学生の成績) :-
        !,
         nth1(_要素位置,Lines,[_学籍番号|_学生の成績]).
二分探索法を使い学生の成績を得る(_要素位置_1,_要素位置_2,Lines,_学籍番号,_学生の成績) :-
        succ(_要素位置_1,1,_要素位置_2),!,
        求める要素は_要素位置_1か_要素位置_2のどちらかにある(_要素位置_1,_要素位置_2,Lines,_学籍番号,_学生の成績),
二分探索法を使い学生の成績を得る(_要素位置_1,_要素位置_2,Lines,_学籍番号,_学生の成績) :-
        _検索位置 is (_要素位置_1 + _要素位置_2) // 2,
        nth1(_検索位置,Lines,[_学籍番号_1|_学生の成績_1]),
        二分探索法を使い学生の成績を得る(_検索位置,_要素位置_1,_要素位置_2,Lines,_学籍番号_1,_学生の成績_1,_学籍番号,_学生の成績).

二分探索法を使い学生の成績を得る(_検索位置,_要素位置_1,_要素位置_2,Lines,_学籍番号,_学生の成績,_学籍番号,_学生の成績) :- !.
二分探索法を使い学生の成績を得る(_検索位置,_要素位置_1,_要素位置_2,Lines,_学籍番号_1,_,_学籍番号,_学生の成績) :-
        _学籍番号_1 @< _学籍番号,
        二分探索法を使い学生の成績を得る(_要素位置_1,_検索位置,Lines,_学籍番号,_学生の成績).
二分探索法を使い学生の成績を得る(_検索位置,_要素位置_1,_要素位置_2,Lines,_学籍番号_1,_,_学籍番号,_学生の成績) :-
        _学籍番号_1 @> _学籍番号,
        二分探索法を使い学生の成績を得る(_検索位置,_要素位置_2,Lines,_学籍番号,_学生の成績).

求める要素は_要素位置_1か_要素位置_2のどちらかにある(_要素位置_1,_要素位置_2,Lines,_学籍番号,_学生の成績) :-
        nth1(_要素位置_1,Lines,[_学籍番号|_学生の成績]),!.
求める要素は_要素位置_1か_要素位置_2のどちらかにある(_要素位置_1,_要素位置_2,Lines,_学籍番号,_学生の成績) :-
        nth1(_要素位置_2,Lines,[_学籍番号|_学生の成績]).

重複要素を許す降順整列([],[]).
重複要素を許す降順整列([_軸要素|_残りならび],_合計得点の重複要素を許す降順ならび) :-
        重複要素を許す降順分割(_軸要素,_残りならび,_軸要素と等しいか大きいならび,_軸要素より小さいならび),
        重複要素を許す降順整列(_軸要素と等しいか大きいならび,_合計得点の重複要素を許す降順ならび_1),
        重複要素を許す降順整列(_軸要素より小さいならび,_合計得点の重複要素を許す降順ならび_2),
        append(_合計得点の重複要素を許す降順ならび_1,[_軸要素|_合計得点の重複要素を許す降順ならび_2],_合計得点の重複要素を許す降順ならび).

重複要素を許す降順分割(_,[],[],[]) :- !.
重複要素を許す降順分割(_軸要素,[A|R],[A|R2],R3) :-
        A @>= _軸要素,
        重複要素を許す降順分割(_軸要素,R1,R2,R3).
重複要素を許す降順分割(_軸要素,[A|R],R2,[A|R3]) :-
        A @< _軸要素,
        重複要素を許す降順分割(_軸要素,R1,R2,R3).

'学生の成績(含:3科目の合計点の順位)を表示する'(_学籍番号,_合計得点の重複を許す降順ならび,_学生の成績) :-
        _学生の成績 = [_科目Aの得点,_科目Bの得点,_科目Cの得点],
        _学生の合計得点 = _科目Aの得点+_科目Bの得点+_科目Cの得点,
        nth1(_順位,_合計得点の重複を許す降順ならび,_学生の合計得点),
        writef('学籍番号 :: %t\n順位 :: #%t\n,科目%t :: %t\n科目%t :: %t\n科目%t :: %t\n',[_学籍番号,_順位,'A',_科目Aの得点,'B',_科目Bの得点,'C',_科目Cの得点]).

get_lines(Lines) :-
        get_lines(user_input,Lines).

get_lines(Stream,Lines) :-
        findall(Line,(
                    get_line(Stream,Line),
                    (   Line=end_of_file,!,fail;
                        true)),
                Lines).

get_line(Stream,X) :-
        get_char(Stream,C),
        get_line_1(Stream,C,Chars),
        atom_chars(X,Chars).

get_line_1(Stream,'\n',[]) :- !.
get_line_1(Stream,end_of_file,[e,n,d,'_',o,f,'_',f,i,l,e]) :- !.
get_line_1(Stream,C,[C|R]) :-
        get_char(Stream,C2),
        get_line_1(Stream,C2,R).

get_line(X) :-
        get_line(user_input,X).