このディレクトリの索引
http://pc12.2ch.net/test/read.cgi/tech/1244449887/481 
#  [1] 授業単元:ソフトウェア演習C 
#  [2] 問題文: 
#  文書ないのすべての単語とその単語の頻度をメンバとして持つ構造体を定義し、 
#  この構造体へのポインタをノードの値として持つ二分木のノードを定義せよ 
#  
#  次に、任意のノードはその左の部分木にはそのノードの単語より辞書順で
#  小さい単語のみがあり、その右の部分木にはより大きい単語のみがあるように
#  保持される。 
#  新たに単語がすでに木にあるかどうかを探すには、ルート(根元)から出発して
#  そのノードに格納されている単語と新しい単語を比較する。 
#  二つが一致したら、それで良い。 
#  新しい単語が木の単語より小さいときは、探索は左の子供に対して続けられ、
#  そうでなければ右の子供が調べられる。 
#  求める方向に子供がないときは、新しい単語は木の中にはないと言うことであり、
#  また実際にはその子供のないところがそれを置く場所である。 
#  このプロセスは再帰的である必要があり、単語の挿入を行うadd_word()関数を
#  定義せよ。
#  この関数は再帰的に呼ばれて、左または右の部分木に振り分けられる。 
#  単語は木の中の単語と一致する(その場合カウント(頻度)がインクリメントされる)か、 
#  あるいはノードを作成し、木に加えなければならないことを示すヌル・ポインタと
#  出会う。 
#  新たにノードが生成されると、この関数ではそのノードへのポインタが返され、
#  親ノードに埋め込まれる。 
#  この関数を利用し、以下のテキストをコマンド実行時の引数として与えられた
#  ファイルを入力して二分探索木を生成し、単語と頻度のリストを表示する
#  プログラムを作成せよ。 

#  
#  文章: ファイル名:test.txt 
#  University was founded in April 1998 at Iwate, 
#  which is situated in the northeastern part of Japan.
#  University consists of four faculties Software and Information Science,
#  Nursing, Social Welfare, 
#  and policy Studies, and additionally other educational supporut centers. 

二分木に情報と頻度を保持する :-
        get_chars('test.txt',Chars),
        chars_split(Chars,[' ',',','.'],WordList),
        木作成(WordList).

情報と頻度を保持した二分木の昇順表示 :-
        二分木から値と頻度を取り出す(1,_頻度付きの値ならび),
        member([_語,_頻度],_頻度付きの値ならび),
        write_formatted('語彙=%t,頻度=%t\n',[_語,_頻度]),
        fail;
        true.

木作成(_ならび) :-
        abolish(節/5),
        節作成(_ならび,1,1,_).

木作成([],_,_,_).
木作成([_値|R],_節,_開始節番号,_次の節番号) :-
        to_lower(_値,_小文字化した値),
        節作成(_小文字化した値,_節,_開始節番号,_受取節番号),
        木作成(R,_節,_受取節番号,_次の節番号).

節作成(_値,_節,_受取節番号,_次の節番号) :- 
        not(節(_節,_,_,_,_)),
        _左 is _受取節番号+1,
        _右 is _受取節番号+2,
        _次の節番号 is _受取節番号+3,
        assertz(節(_節,_左,_右,_値,1)),!.
節作成(_値,_節,_受取節番号,_次の節番号) :-
        節(_節,_左,_右,_値2,_),
        _値 @< _値2,
        節作成(_値,_左,_受取節番号,_次の節番号).
節作成(_値,_節,_受取節番号,_次の節番号) :-
        節(_節,_左,_右,_値2,_),
        _値 @> _値2 ,
        節作成(_値,_右,_受取節番号,_次の節番号).
節作成(_値,_節,_受取節番号,_次の節番号) :-
        節(_節,_左,_右,_値2,_頻度),
        _値 = _値2 ,
        _頻度2 is _頻度 + 1,
        retract(節(_節,_左,_右,_値2,_頻度)),
        assertz(節(_節,_左,_右,_値2,_頻度2)).

二分木から値と頻度を取り出す(_節,_頻度付きの値ならび) :-
        findall([_値,頻度],二分木から値と頻度を取り出す(_節,_,_値,_,_頻度),_頻度付きの値ならび).

二分木から値と頻度を取り出す(_節,_値1,_値,_頻度1,_頻度) :-
        節(_節,_左,_,_値2,_,_頻度2),
        二分木から値と頻度を取り出す(_左,_値2,_値,_頻度2,_頻度).
二分木から値と頻度を取り出す(_節,_値1,_値,_頻度1,_頻度) :-
        節(_節,_,_右,_値2,_頻度2),
        二分木から値と頻度を取り出す(_右,_,_値,_,_頻度).
二分木から値と頻度を取り出す(_節,_値1,_値,_頻度1,_頻度) :-
        not(var(_値1)),
        not(var(_頻度1)),
        _値1=_値,
        _頻度1=_頻度.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

get_chars(File,Chars) :-
        open(File,read,Input),
        findall(X,(repeat,get_char(Input,X),(X=end_of_file,!,fail;true)),Chars),
        close(Input).

concat_atom([A],Sep,[A]) :- !.
concat_atom([A|R],Sep,X) :-
        concat_atom(R,Sep,Y),
        atom_concat(A,Sep,Y1),
        atom_concat(Y1,Y,X).

chars_split(L,SeparatesL,WordsList) :-
        split_1(L,SeparatesL,WordsList),!.

split_1([],SeparatersL,[]).
split_1(L1,SeparatersL,[A|R]) :-
        not(L1=[]),
        split_2(L1,SeparatersL,L2,R2),
        not(L2=[]),
        atom_chars(A,L2),
        split_1(R2,SeparatersL,R).
split_1(L1,SeparatersL,X) :-
        not(L1=[]),
        split_2(L1,SeparatersL,L2,R2),
        L2=[],
        split_1(R2,SeparatersL,X).

split_2([],_,[],[]).
split_2(L1,SeparatersL,[],R) :-
        member(L2,SeparatersL),
        append(L2,R,L1).
split_2([A|R1],SeparatersL,[A|R2],R) :-
        not((member(L2,SeparatersL),append(L2,_,[A|R1]))),
        split_2(R1,SeparatersL,R2,R).

区切り語ならびの変形(_区切り語ならび,_降順の区切り文字ならびのならび) :-
        sort(_区切り語ならび,_昇順の区切り語ならび),
        reverse(_昇順の区切り語ならび,_降順の区切り語ならび),
        atomList2charsList(_降順の区切り語ならび,_降順の区切り文字ならびのならび).

atomList2charsList([],[]) :- !.
atomList2charsList([A|R1],[L|R2]) :-
        atom_chars(A,L),
        atomList2charsList(R1,R2).