このディレクトリの索引
http://pc12.2ch.net/test/read.cgi/tech/1260532772/678
# [1] 授業単元: 基礎プログラミングおよび演習
# [2] 問題文(含コード&リンク): http://ime.nu/kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10352.txt
#
# あるWebページに対する24時間分の閲覧者の名前、閲覧開始時刻および閲覧継続時間を表す「閲覧データ」があるとしよう。
# 1名以上の閲覧データから、閲覧している人数がもっとも多い30分刻みでの時間帯を求め、そのときの閲覧者名を印字する
# プログラムを作成せよ。状況によっては日をまたぐこともあるが、ここではどの時間帯に閲覧が多いのかを知りたいので
# 日の違いは考えなくてよい。各閲覧データは標準入力から、
#
# 閲覧者名
# 閲覧開始時刻 閲覧継続時間
#
# の2行で与えられる。ここで閲覧者名は英小文字2文字の後に4桁の数字が続く。閲覧開始時刻は24時間制での時を100倍し、
# 分を加えた数を表す4桁の数字、閲覧継続時間は分を表す高々3桁の数字である。時刻および時間は30分刻み(つまり0分か30分)
# である。たとえば、
#
# ku7535
# 0130 60
#
# は、名前がku7535、開始時刻が1時30分、継続時間が60分、つまり1時30分から2時30分直前まで閲覧していたことを表す。
#   まず閲覧データに対する構造体 user を定義し、それを要素とする大きさNの大域的な配列 users を用意せよ(Nはマクロ
# である)。次に、N人分のデータを読み込むか、閲覧者名としてアスタリスク(*)が与えられるまで、標準入力から閲覧データを
# 読み込み、配列 users にセットするとともに閲覧データを返す関数 int read_users(void) を作成せよ。最後に配列 users の
# 先頭からn個の閲覧データを対象に、24時間中で最大人数が閲覧している30分刻みでの時間帯と、そのときの閲覧者名を印字
# する関数 void print_prime_time(int n) を定義せよ。ただし最大閲覧者数となる時間帯は一般に複数あることに注意すること。
# さらに以下のmain関数と組み合わせてプログラムを作成せよ。 

標準入力から閲覧履歴読み込む(_閲覧履歴ならび) :-
    get_lines(Lines),
    閲覧者情報の取得(Lines,_閲覧履歴ならび),
    閲覧者履歴の登録(_閲覧者履歴ならび),!.

閲覧履歴の取得と登録([],[]) :- !.
閲覧履歴の取得と登録([_閲覧者名,B|R1],[[_閲覧者名,_閲覧開始時刻,_閲覧継続時間]|R2]) :-
    split(B,[' '],[_閲覧開始時刻,_閲覧継続時間]),
    assertz(閲覧履歴(_閲覧者名,_閲覧開始時刻,_閲覧継続時間)),
    閲覧履歴の取得と登録(R1,R2),!.

先頭からn個の閲覧データを対象に、24時間中で最多人数が閲覧している30分刻みでの時刻と、そのときの閲覧者名を印字(N,_時,_分,_閲覧者ならび) :-
    先頭からn個の閲覧データを対象に、24時間中で最多人数が閲覧している30分刻みでの時刻と、そのときの閲覧者名(N,_閲覧履歴ならび,_時刻,_閲覧者ならび),
    _時 is _時刻 // 100,
    _分 is _時刻 mod 100,
    concat_atom(_閲覧者ならび,' ',_閲覧者ならび表示),
    write_formatted('最多閲覧時間 %t時%t分から %t\n',[_時,_分,_閲覧者ならび表示]).

先頭からn個の閲覧データを対象に、24時間中で最多人数が閲覧している30分刻みでの時刻と、そのときの閲覧者名(N,_閲覧履歴ならび,_時刻,_閲覧者ならび) :-
    先頭からn個の閲覧データを対象に(N,_閲覧履歴ならび,_先頭からn個のデータ),
    閲覧分布ならびを作る(_先頭からn個のデータ,_履歴分布ならび),
    最多閲覧者時刻(_履歴分布ならび,_最多閲覧者時刻ならび),
    member(_時刻,_最多閲覧者時刻),
    setof(_閲覧者名,member([_閲覧者名,_時刻,_],_履歴分布ならび),_閲覧者ならびの一).    

先頭からn個の閲覧データを対象に(N,_閲覧履歴ならび,_先頭からn個のデータ) :-
    length(_先頭からn個のデータ,N),
    append(_先頭からn個のデータ,_,_閲覧履歴ならび),!.

閲覧分布ならびを作る([],[]) :- !.
閲覧分布ならびを作る([[_閲覧者名,_閲覧開始時刻,_閲覧継続時間]|R1],X) :-
    閲覧継続時間を30分ごとに刻む(_閲覧者名,_閲覧開始時刻,_閲覧継続時間,L),
    閲覧分布ならびを作る(R1,Y),
    append(L,Y,X).

閲覧継続時間を30分ごとに刻む(_,_,0,[]) :- !.
閲覧継続時間を30分ごとに刻む(_閲覧者名,_閲覧開始時刻,_閲覧継続時間,[[_閲覧者名,_閲覧開始時刻,30]|R]) :-
    次の30分を閲覧開始時刻とする(_閲覧開始時刻,_次の閲覧開始時刻),
    _閲覧継続時間2 is _閲覧継続時間 - 30,
    閲覧継続時間を30分ごとに刻む(_閲覧者名,_次の閲覧開始時刻,_閲覧継続時間2,R),!.

次の30分を閲覧開始時刻とする(2330,0) :- !.
次の30分を閲覧開始時刻とする(_閲覧開始時刻,_次の閲覧開始時刻) :-
    30 is _閲覧開始時刻 mod 100,
    _次の閲覧開始時刻 is _閲覧開始時刻 - 30 + 100,!.
次の30分を閲覧開始時刻とする(_閲覧開始時刻,_次の閲覧開始時刻) :-
    0 is _閲覧開始時刻 mod 100,
    _次の閲覧開始時刻 is _閲覧開始時刻 + 30,!.

最多閲覧者時刻(_履歴分布ならび,_最多閲覧者時刻ならび) :-
    findall(L1,setof(_閲覧開始時刻,member([_,_閲覧開始時刻,_],_履歴分布ならび),L1),L2),
    最多閲覧者時刻の二(L2,_履歴分布ならび,L3),
    findmax(Count,member([Count,_,_],L3),Max),
    findall([_閲覧開始時刻,_閲覧者ならび],member([Max,_閲覧開始時刻,_閲覧者ならび],L3),_最多閲覧者時刻ならび).

最多閲覧者閲覧開始時刻の二([],_,[]) :- !.
最多閲覧者閲覧開始時刻の二([[_閲覧開始時刻]|R1],_履歴分布ならび,[[Count,_閲覧開始時刻,L1]|R2]) :-
    findall([_閲覧者名,_閲覧開始時刻],member([_閲覧者,_閲覧開始時刻,_],_履歴分布ならび),L1),
    length(L1,Count),
    最多閲覧者閲覧開始時刻の二(R1,_履歴分布ならび,R2).