このディレクトリの索引
http://pc12.2ch.net/test/read.cgi/tech/1260532772/10
#  [1]単元 初等C言語 
#  [2]問題 コンソールから、年月日時分秒に対応する整数をそれぞれ個別に不正入力時には 
#  再入力を促しながら読み込み、それをyyyymmddhhmmss(準グレゴリオ暦)形式の時刻表 
#  現と解釈する。この処理を2回行い2つの時刻表現を取得する。それぞれが正しいフォー 
#  マットかどうかを調べ、共に正しい場合は、日付が新しいものの順に 
#  yyyy年mm月dd日hh時mm分ss秒の書式で出力)しその時刻差を秒単位、分単位、時間単 
#  位、日単位で出力するプログラム(小数点一位以下四捨五入) 
#  但し1900年1月1日0時0分0秒以前の時刻は与えられないとして良い。 
#  また9999年12月31日23時59分59秒以後の時刻も与えられないとする。 
#  うるう年は400の倍数か100の倍数でない4の倍数な年であるとし、2月の末日 
#  にうるう日が付与されるものとする。実際の暦体系では不定期に付与されるうるう秒 
#  は考慮しなくて良いものとする正しい日付でない場合はその旨出力し処理を中止する 

二つの時刻の時間差を表示する :-
    準グレゴリオ暦入力(_準グレゴリオ暦1,_年1,_月1,_日1,_時1,_分1,_秒1),
    準グレゴリオ暦入力(_準グレゴリオ暦2,_年2,_月2,_日2,_時2,_分2,_秒2),
    二つの時刻の時間差を計算する(_年1,_月1,_日1,_時1,_分1,_秒1,_年2,_月2,_日2,_時2,_分2,_秒2,_総秒差,_分数,_時間数,_分数,_余り秒数,_時間数,_余り分数,_日数,_余り時間数),
    時間差を表示する(_準グレゴリオ暦1,_準グレゴリオ暦2,_総秒差,_分数,_時間数,_分数,_余り秒数,_時間数,_余り分数,_日数,_余り時間数).

二つの時刻の時間差を計算する(_年1,_月1,_日1,_時1,_分1,_秒1,_年2,_月2,_日2,_時2,_分2,_秒2,_総秒差,_分数,_時間数,_分数,_余り秒数,_時間数,_余り分数,_日数,_余り時間数) :-
    何日あるか(_年1,_月1,_日1,_年2,_月2,_日2,_何日1),
    時・分・秒調整(_時1,_分1,_秒1,_時2,_分2,_秒2,_何日1,_何日2,_秒),
    _総秒数 is 38400 * _何日 + _秒,
    _分数 is _総秒数 // 60,
    _余り秒数 is _総秒数 mod 60,
    _時間数 is _分数 // 60,
    _余り分数 is _分数 mod 60,
    _余り時間数 is _時間 mod 38400,!.

時間差を表示する(_準グレゴリオ暦1,_準グレゴリオ暦2,_総秒差,_分数,_時間数,_分数,_余り秒数,_時間数,_余り分数,_日数,_余り時間数) :-
    writef('それぞれの時刻の準グレゴリオ暦表現は %t\n%t\n',[_準グレゴリオ暦1,_準グレゴリオ暦2]),
    writef('時刻差は秒差で%t秒\n',[_総秒差]),
    writef('分差で%t分と%t秒\n',[_分数,_余り秒数]),
    writef('時間差で%t時間と%分と%秒\n',[_時間,_余り分数,_余り秒数]),
    writef('日差は%t日と%t時間と%t分と%秒です\n',[_日数,_余り時間数,_余り分数,_余り秒数]),!.

準グレゴリオ暦入力(_準グレゴリオ暦,_年,_月,_日,_時,_分,_秒) :-
    repeat,
    催促付き整数入力('西暦年 yyyy:',_年),整数から文字列(4,_年,_年文字列),
    催促付き整数入力('月 mm:',_月),整数から文字列(2,_月,_月文字列),
    催促付き整数入力('月 dd:',_日),整数から文字列(2,_日,_日文字列),
    催促付き整数入力('月 hh:',_時),整数から文字列(2,_時,_時文字列),
    催促付き整数入力('月 mi:',_分),整数から文字列(2,_分,_分文字列),
    催促付き整数入力('月 ss:',_秒),整数から文字列(2,_秒,_秒文字列),
    その日付はありうるか(_年,_月,_日,_時,_分,_秒),
    concat_atom([_年文字列,_月文字列,_日文字列,_時文字列,_分文字列,_秒文字列],_準グレゴリオ歴),!.

その日付はありうるか(_年,_月,_日,_時,_分,_秒) :-
    _年>=1900,_年=<9999,
    _時>=0,_時=<59,
    _分>=0,_分=<59,
    _秒>=0,_秒=<59,
    その日付はありうるか(_年,_月,_日),!.
その日付はありうるか(_年,_月,_日,_時,_分,_秒) :-
    write('日付として不適切なものでした\n'),fail.

その日付はありうるか(_年,2,_日) :-
    うるう年(_年),
    _日>=1,_日=<29,!.
その日付はありうるか(_年,2,_日) :-
    \+(うるう年(_年)),
    _日>=1,_日=<29,!.
その日付はありうるか(_年,_月,_日) :-
    member(_月,[1,3,5,7,8,10,12]),
    _日>=1,_日=<31,!.
その日付はありうるか(_年,_月,_日) :-
    member(_月,[4,6,9,11]),
    _日>=1,_日=<30,!.

何日あるか(_年,_月1,_日1,_年,_月2,_日2,_何日あるか) :-
    今日から大晦日まで何日あるか(_年,_月1,_日1,_何日),
    今日は元旦から何日目(_年,_月2,_日2,_元旦から何日目),
    _何日あるか is _何日 + _元旦から何日目 - 1,!.
何日あるか(_年1,_月1,_日1,_年2,_月2,_日2) :-
    _年2 is _年 + 1,
    今日から大晦日まで何日あるか(_年1,_月1,_日1,_何日),
    今日は元旦から何日目(_年2,_月2,_日2,_元旦から何日目),
    _何日あるか is _何日 + _元旦から何日目,!.
何日あるか(_年1,_月1,_日1,_年2,_月2,_日2) :-
    _年11 is _年1 + 1,
    _年22 is _年2 - 1,
    うるう年回数(_年11,_年22,_うるう年回数),
    N is (_年22-_年11+1) * 365 + _うるう年回数,
    今日から大晦日まで何日あるか(_年1,_月1,_日1,_何日),
    今日は元旦から何日目(_年,_月,_日,_元旦から何日目),
    _何日あるか is _何日 + _元旦から何日目 + N,!.

時・分・秒調整(_時1,_分1,_秒1,_時2,_分2,_秒2,_何日1,_何日2,_秒) :-
    _時間1 is 3600 * _時1 + _分1 * 60 + _秒1,
    _時間2 is 3600 * _時2 + _分2 * 60 + _秒2,
    _秒3 is _時間2 - _時間1,
    ( _秒3 >= 0,
      _何日2 is _何日 - 1,
      _秒3 = _秒;
      _秒3 < 0,
      _何日2 is _何日 - 2,
      _秒2 is 3600*24-_秒3
    ),!.

日・時変換(_日,_時) :- _時 is _日 * 24.

日・分変換(_日,_分) :- _分 is _日 * 24 * 60.

日・秒変換(_日,_秒) :- _秒 is _日 * 24 * 60 * 60.

催促付き整数入力('年 yyyy:',_年),_年>=1900,_年=<9999,
催促付き整数入力('月 mm:',_月),
催促付き整数入力('年 dd:',_日),

うるう年(_年) :- 0 is _年 mod 400,!.
うるう年(_年) :- 0 is _年 mod 100,!,fail.
うるう年(_年) :- 0 is _年 mod 4,!.
うるう年(_年) :- \+(0 is _年 mod 4),fail.

月別日数ならび(平年,[31,28,31,30,31,30,31,31,30,31,30,31]).
月別日数ならび(うるう年,[31,29,31,30,31,30,31,31,30,31,30,31]).

うるう年回数(_起点西暦年,_終点西暦年,_うるう年回数) :-
    count((between(_起点西暦年,_終点西暦年,N),うるう年(N)),_うるう年回数).

今日は元旦から何日目(_年,_月,_日,_元旦から何日目) :-
    うるう年(_年),
    月別日数ならび(うるう年,_月別日数ならび),
    N1 is _月-1,
    append(L1,_,_月別日数ならび),
    length(L1,N1),
    sum(L1,_前月までの合計日数),
    _元旦から何日目 is _前月までの合計日数 + _日,!.
今日は元旦から何日目(_年,_月,_日,_元旦から何日目) :-
    \+(うるう年(_年)),
    月別日数ならび(平年,_月別日数ならび),
    N1 is _月-1,
    append(L1,_,_月別日数ならび),
    length(L1,N1),
    sum(L1,_前月までの合計日数),
    _元旦から何日目 is _前月までの合計日数 + _日,!.

今日から大晦日まで何日あるか(_年,_月,_日,_何日) :-
    うるう年(_年),
    今日は元旦から何日目(_年,_月,_日,_元旦から何日目),
    _何日 is 366 - _元旦から何日 + 1.
今日から大晦日まで何日あるか(_年,_月,_日,_何日) :-
    \+(うるう年(_年)),
    今日は元旦から何日目(_年,_月,_日,_元旦から何日目),
    _何日 is 365 - _元旦から何日 + 1.