このディレクトリの索引
http://pc12.2ch.net/test/read.cgi/tech/1245853701/606 
# [1] 授業単元:C 
# [2] 問題文(含コード&リンク): 
# http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/9680.txt 
# http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/9678.txt 
# ・リストを用いた成績処理
# ・リストを用いて個人データを格納する表を作成
#  ・処理番号を入力して処理の切り替えを行う
# - 1.成績一覧表示, 2.個人成績表示,
#   3.個人平均点表示,4.科目平均点表示,
#   0.終了
#  ・リストに新たにデータを追加する時は学生番号順に並ぶように追加する.
#  ・リスト構成する要素(セル)はmalloc関数でヒープ領域から確保するものとする.
# 入力する成績データ(この順番で入れる)
# 学番名前英語数学化学物理
# 106 tada 65 80 90 100
# 101 kouda 50 85 70 65
# 103 hanako 70 75 65 80
# 104 akane 60 95 80 75
# 102 tarou 90 80 85 65
# 105 nara 80 70 50 95

処理番号を入力して処理の切り替えを行う :-
個人データのロード,
forall((処理番号入力して(X),('0が入力されたら個人データをセーブして終了する'(X),!,fail;true)),処理の切り替えを行う(X)).

処理番号入力して(X) :-
repeat,
入力プロンプト,
整数を得る(処理番号を入力してください,true,X).

'0が入力されたら個人データをセーブして終了する'(0) :-
個人データのセーブ,
write('処理を終了します\n').

処理の切り替えを行う(0) :- !.
処理の切り替えを行う(1) :- 成績一覧表示.
処理の切り替えを行う(2) :- 個人成績表示.
処理の切り替えを行う(3) :- 個人平均点表示.
処理の切り替えを行う(4) :- 科目別平均表示.
処理の切り替えを行う(7) :- 個人データの格納.

入力プロンプト :-
write('1.成績一覧表示, 2.個人成績表示,\n3.個人平均点表示,4.科目平均点表示,\n7. 個人データの追加, \n0. 終了\n').

個人成績表示 :-
学番を得る(_学番),
個人データを得て個人合計点と個人平均点を得る(_学番,_英語,_数学,_科学,_物理,_合計,_平均),
write('学番 名前     英語 数学 化学 物理 合計 平均\n'),
write_formatted('%3d %8s %3d %3d %3d %3d %3d %3d\n',[_学番,B,C,D,E,F,_合計点,_個人平均点]).

学番を得る(_学番) :-
整数を得る(学番を入れてください,true,_学番).

個人データを得て個人合計点と個人平均点を得る(_学番,_英語,_数学,_科学,_物理,_合計,_平均) :-
個人データ(_学番,B,C,D,E,F),
個人平均点(_学番,_個人平均点),
個人合計点(_学番,_個人合計点).

個人平均点表示 :-
整数を得る(学番を入れて下さい,true,_学番),
個人平均点(_学番,_個人平均点),
個人データ(_学番,_氏名,_,_,_,_),
writef('%t %8s の平均点は %tです\n',[_学番,_氏名,_個人平均点]).

科目別平均表示 :-
四科目の科目別平均を得る(_英語平均点,_数学平均点,_物理平均点,_化学平均点),
writef('科目別の平均は 英語=%3d 数学=%3d 物理=%3d 化学=%3d です\n',
[_英語平均点,_数学平均点,_物理平均点,_化学平均点]).

四科目の科目別平均を得る(_英語平均点,_数学平均点,_物理平均点,_化学平均点) :-
科目別平均(英語,_英語平均点),
科目別平均(数学,_数学平均点),
科目別平均(物理,_物理平均点),
科目別平均(化学,_化学平均点).

個人平均点(_学番,_個人平均点) :-
個人データ(_学番,_,C,D,E,F),
_個人平均点 is truncate(round(C+D+E+F) / 4)).

個人合計点(_学番,_個人合計点) :-
個人データ(_学番,_,C,D,E,F),
_個人平均 is truncate(round((C+D+E+F) / 4)).

科目別平均点(_科目,_平均点) :-
findavg(U,(鍵位置(_科目,_,P,U),call(P)),_平均点の一),
_平均点 is truncate(round(_平均点の一)).

科目別合計点(_科目,_合計点) :-
findsum(U,(鍵位置(_科目,_,P,U),call(P)),_合計点の一).
_合計点 is truncate(round(_合計点の一)).

成績一覧表示 :-
    write('学番 名前     英語 数学 化学 物理 合計 平均\n'),
    個人データ(A,B,C,D,E,F),
    個人合計点(A,_合計点),
    個人平均点(A,_平均点),
    write_formatted('%3d %8s %3d %3d %3d %3d %3d %3d\n',[A,B,C,D,E,F,_合計点,_平均点]),
    fail;
    科目別合計点(英語,_英語合計点),
    科目別合計点(数学,_数学合計点),
    科目別合計点(物理,_物理合計点),
    科目別合計点(化学,_化学合計点),
    科目別平均点(英語,_英語平均点),
    科目別平均点(数学,_数学平均点),
    科目別平均点(物理,_物理平均点),
    科目別平均点(化学,_化学平均点),
    加算([_英語合計点,_数学合計点,_物理合計点,_化学合計点],_全員合計点),
    _全員平均点 is truncate(round(_全員合計点 / 4)),
    writef('合計         %3d %3d %3d %3d %3d\n,
     [_英語合計点,_数学合計点,_物理合計点,_化学合計点,_全員合計点]),
    writef('平均         %3d %3d %3d %3d %3d\n,
        [_英語平均点,_数学平均点,_物理平均点,_化学平均点,_全員平均点]).

個人データの格納 :-
findall(K,個人データ(K),Ls),
個人データの格納(Ls).

個人データの格納(Ls) :-
    writef('個人データ入力 (学番 名前 英語 数学 化学 物理): '),
    get_line(Line),
    not(Line==end_of_file),
    split(Line,[' ',','],_個人データ),
    リストに挿入(_個人データ,Ls,Ls1),
    個人データの格納(Ls1).
個人データの格納(Ls) :-
    abolish(個人データ/1),
    member(L,Ls),
    P =.. [個人データ|L],
    assertz(P),
    fail;
    true.

個人データのロード :-
    exists('個人データ#6.pro',read),
    consult('個人データ#6.pro').
個人データのロード.

個人データのセーブ :-
    tell('個人データ#4.pro'),
    listing,
    told.

リストに挿入(L,[],[L]) :- !.
リストに挿入([K|R1],[[A|R2]|R3],[[A|R2]|R4]) :-
    K @>= A,
    リストに挿入([K|R1],R3,R4).
リストに挿入([K|R1],[[A|R2]|R3],[[K|R1],[A|R2]|R3]) :-
    K @< A,!.

鍵位置(学番,[_学番,_,_,_,_,_],個人データ(_学番,_,_,_,_,_),_学番).
鍵位置(名前,[_,_名前,_,_,_,_],個人データ(_,_名前,_,_,_,_),_名前).
鍵位置(英語,[_,_,_英語,_,_,_],個人データ(_,_,_英語,_,_,_),_英語).
鍵位置(数学,[_,_,_,_数学,_,_],個人データ(_,_,_,_数学,_,_),_数学).
鍵位置(化学,[_,_,_,_,_化学,_],個人データ(_,_,_,_,_化学,_),_化学).
鍵位置(物理,[_,_,_,_,_,_物理],個人データ(_,_,_,_,_,_物理),_物理).

findsum(_選択項,_項,_合計値) :-
    findall(_選択項,_項,_値ならび),
    '加算'(_値ならび,_合計値),!.

findavg(_集約項,_項,_算術平均) :-
    findall(_集約項,_項,_値ならび),
    '加算'(_値ならび,_合計値),
    length(_値ならび,_ならびの長さ),
    _算術平均 is _合計値 / _ならびの長さ,!.

加算([],0.0) :- !.
加算([A|R],S) :-
    加算(R,S2),
    S is A + S2.