このディレクトリの索引
#  出題場所 :: http://toro.2ch.net/test/read.cgi/tech/1381909900/576
#  西暦何年かを入力するとその年に月曜日が何回あるか数え 
#  52回なら1を、53回なら0を出力するプログラムお願いします… 
#   
#  1回1回判定するのではなく、一気に何回か入力し、一気に判定を出力するものでお願いします 
#  (0を入力したら終わりです) 
#   
#  入力できるのは1989〜5000です 
# 
# 

'西暦何年かを入力するとその年に月曜日が何回あるか数え
52回なら1を、53回なら0を出力するプログラムお願いします…
1回1回判定するのではなく、一気に何回か入力し、一気に判定を出力するものでお願いします 
(0を入力したら終わりです) 
入力できるのは1989〜5000です' :-
        '西暦何年かを一気に何回か入力し(0を入力したら終わりです) 入力できるのは1989〜5000です'(_西暦ならび),
        'その年に月曜日が何回あるか数え52回なら1を、53回なら0を出力する'(_西暦ならび).

'西暦何年かを一気に何回か入力し(0を入力したら終わりです) 入力できるのは1989〜5000です'(_西暦ならび) :-
findall(_西暦,(
'西暦を入力し(0を入力したら終わりです) 入力できるのは1989〜5000です'('西暦(1989~5000)を入力して下さい',_西暦),( _西暦=0,!,fail;true)),_西暦ならび).

'その年に月曜日が何回あるか数え52回なら1を、53回なら0を出力する'([]).
'その年に月曜日が何回あるか数え52回なら1を、53回なら0を出力する'([_西暦|_残りならび]) :-
        'その年に月曜日が何回あるか数え52回なら1を、53回なら0を'(_西暦,_0または1),
        writef('%t年 %t\n',[_西暦,_0または1]),
        'その年に月曜日が何回あるか数え52回なら1を、53回なら0を出力する'(_残りならび).

'その年に月曜日が何回あるか数え52回なら1を、53回なら0を'(_西暦,_0または1) :-
        うるう年で1月1日が日曜か月曜の時は0それ以外は1(_西暦,_0または1).
'その年に月曜日が何回あるか数え52回なら1を、53回なら0を'(_西暦,_0または1) :-
        うるう年でない年は1月1日が月曜の時は0それ以外は1(_西暦,_0または1).

うるう年で1月1日が日曜か月曜の時は0それ以外は1(_西暦,0) :-
        うるう年(_西暦),
        '1月1日が日曜か月曜の時は'(_西暦),!.
うるう年で1月1日が日曜か月曜の時は0それ以外は1(_西暦,1) :-
        うるう年(_西暦).

'1月1日が日曜か月曜の時は'(_西暦) :-
        'Zellerの公式を用いて曜日を得る'(_西暦,1,1,_曜日を表す値,_曜日),
        member(_曜日,[日曜,月曜]).

うるう年でない年は1月1日が月曜の時は0それ以外は1(_西暦,0) :-
        \+(うるう年(_西暦)),
        'Zellerの公式を用いて曜日を得る'(_西暦,1,1,_曜日を表す値,月曜),!.
うるう年でない年は1月1日が月曜の時は0それ以外は1(_西暦,1) :-
        \+(うるう年(_西暦)).

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

'Zellerの公式を用いて曜日を得る'(_年,_月,_日,_曜日を表す値,_曜日) :-
        'Zellerの公式では1月と2月はそれぞれ前年の13月と14月に変換して計算する'(_年,_月,_日,_曜日を表す値,_曜日).
'Zellerの公式を用いて曜日を得る'(_年,_月,_日,_曜日を表す値,_曜日) :-
        _月 > 2,
        _曜日を表す値 is (_年 + truncate(_年 / 4) - truncate(_年 / 100) + truncate(_年 / 400) + truncate((13 * _月 + 8) / 5) + _日) mod 7,
        曜日を表す値(_曜日を表す値,_曜日).

'Zellerの公式では1月と2月はそれぞれ前年の13月と14月に変換して計算する'(_年,_月,_日,_曜日を表す値,_曜日) :-
        _月 =< 2,
        _年_1 is _年 - 1,
        _月_2 is _月 + 12,
        'Zellerの公式を用いて曜日を得る'(_年_1,_月_2,_日,_曜日を表す値,_曜日).

曜日を表す値(0,日曜).
曜日を表す値(1,月曜).
曜日を表す値(2,火曜).
曜日を表す値(3,水曜).
曜日を表す値(4,木曜).
曜日を表す値(5,金曜).
曜日を表す値(6,土曜).

'西暦を入力し(0を入力したら終わりです) 入力できるのは1989〜5000です'(_催促文,_西暦) :-
        writef('%t ',[_催促文]),
        get_line(_入力行),
        '診断 :: 西暦を入力し(0を入力したら終わりです) 入力できるのは1989〜5000です'(_入力行,_西暦).
'西暦を入力し(0を入力したら終わりです) 入力できるのは1989〜5000です'(_催促文,_西暦) :-
        '西暦を入力し(0を入力したら終わりです) 入力できるのは1989〜5000です'(_催促文,_西暦).

'診断 :: 西暦を入力し(0を入力したら終わりです) 入力できるのは1989〜5000です'('0',0) :- !.
'診断 :: 西暦を入力し(0を入力したら終わりです) 入力できるのは1989〜5000です'(_入力行,_西暦) :-
        read_term_from_atom(_入力行,_西暦,[]),
        integer(_西暦),
        between(1989,5000,_西暦),!.
'診断 :: 西暦を入力し(0を入力したら終わりです) 入力できるのは1989〜5000です'(_入力行,_) :-
        writef('入力された文字列"%t"から1899年から5000年範囲の西暦が得られませんでした\n再入力をお願いします\n',[_入力行]),
        fail.

get_line(Line) :-
        get_line(user_input,Line).

get_line(Instream,Line) :-
        get_char(Instream,C),
        get_line_1(Instream,C,Chars),
        atom_chars(Line,Chars) .

get_line_1(_,'\n',[]) :-  !.
get_line_1(_,end_of_file,[]) :- !.
get_line_1(Instream,C,[C|R]) :-
        get_char(Instream,C2),
        get_line_1(Instream,C2,R).