このディレクトリの索引
#  出典: プログラムのお題スレ Part4 #38
#  
#  標準入力から与えられたフォーマットを元に年齢を求めて出力せよ
#  標準入力から以下の形式で与えられます
#  YYYY/MM/dd
#  
#  年齢は誕生日の前日に歳を重ねることに注意せよ。4/1生まれの場合は3/31に歳が増えることになる。 

'標準入力から与えられたフォーマットを元に年齢を求めて出力せよ
標準入力から以下の形式で与えられます
YYYY/MM/dd

年齢は誕生日の前日に歳を重ねることに注意せよ。4/1生まれの場合は3/31に歳が増えることになる。' :-
        '標準入力から与えられたフォーマット(YYYY/MM/dd)を元に'(_年,_月,_日),
        '年齢を求めて(年齢は誕生日の前日に歳を重ねることに注意せよ。4/1生まれの場合は3/31に歳が増えることになる)'(_年,_月,_日,_年齢),
        出力せよ(_年齢).

'標準入力から与えられたフォーマット(YYYY/MM/dd)を元に'(_年,_月,_日) :-
        get_line(_文字列),
        read_term_from_atom(_文字列,_年/_月/_日,[]).

'年齢を求めて(年齢は誕生日の前日に歳を重ねることに注意せよ。4/1生まれの場合は3/31に歳が増えることになる)'(_年,_月,_日,_年齢) :-
        date(date(_今日_年,_今日_月,_今日_日)),
        誕生日の前日(_今日_年,_月,_日,_誕生日の前日_年,_誕生日の前日_月,_誕生日の前日_日),
        '年齢を計算する(年齢は誕生日の前日に歳を重ねることに注意せよ)'(_年,_月,_日,_誕生日の前日_年,_誕生日の前日_月,_誕生日の前日_日,_年齢).

誕生日の前日(_年,1,1,_前日_年,12,31) :-
        succ(_前日_年,_年),!.
誕生日の前日(_年,3,1,_年,2,29) :-
        うるう年(_年),!.
誕生日の前日(_年,3,1,_年,2,28) :-
        \+(うるう年(_年)),!.
誕生日の前日(_年,_月,1,_年,_前日_月,31) :-
        member(_月,[2,4,6,9,11]),
        succ(_前日_月,_月),!.
誕生日の前日(_年,_月,1,_年,_前日_月,30) :-
        member(_月,[5,7,8,10,12]),
        succ(_前日_月,_月),!.
誕生日の前日(_年,_月,_日,_年,_月,_前日_日) :-
        succ(_前日_日,_日).

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

'年齢を計算する(年齢は誕生日の前日に歳を重ねることに注意せよ)'(_年,_月,_日,_誕生日の前日_年,_誕生日の前日_月,_誕生日の前日_日,_年齢) :-
        _月 > _誕生日の前日_月,
        _年齢 is _誕生日の前日の年 - _年.
'年齢を計算する(年齢は誕生日の前日に歳を重ねることに注意せよ)'(_年,_月,_日,_誕生日の前日_年,_誕生日の前日_月,_誕生日の前日_日,_年齢) :-
        _月 < _誕生日の前日_月,
        _年齢 is _誕生日の前日の年 - _年 - 1.
'年齢を計算する(年齢は誕生日の前日に歳を重ねることに注意せよ)'(_年,_月,_日,_誕生日の前日_年,_誕生日の前日_月,_誕生日の前日_日,_年齢) :-
        _月 = _誕生日の前日_月,
        _日 >= _誕生日の前日_日,
        _年齢 is _誕生日の前日_年 - _年.
'年齢を計算する(年齢は誕生日の前日に歳を重ねることに注意せよ)'(_年,_月,_日,_誕生日の前日_年,_誕生日の前日_月,_誕生日の前日_日,_年齢) :-
        _月 = _誕生日の前日_月,
        _日 < _誕生日の前日の日,
        _年齢 is _誕生日の前日_年 - _年 - 1.

出力せよ(_年齢) :-
        writef('%t歳です\n',[_年齢]).