このディレクトリの索引
http://hibari.2ch.net/test/read.cgi/tech/1289913298/409
#  [1] 授業単元: プログラミングおよび演習 
#  [2] 問題文(含コード&リンク):  
#   1.解答例のカレンダー(下にリンクはってます)について、dayofweek()を再帰で書き直せ。 
#   ◦ある月の1日の曜日は、前の月の日数と1日の曜日から計算できる 
#    ◦ある年の1月1日の曜日は、前の年の日数と前の年の1月1日の曜日から、あるいは、その年の日数と次の年の1月1日の曜日から計算できる 
#   ◦2000年1月1日は土曜日である 
#    
#   2.このプログラムについて、任意の年月についてdayofweek() の呼び出し回数が何回になるかを理論的に考察せよ。また、呼び出し回数を計測し、結果が実際に理論と合致しているかを確認せよ。 
#    2.ヒント:呼出し回数を数えるためにグローバル変数を使用する 
#   
#  

ある年・ある月の一日の曜日は(_年,_月,_曜日) :-
        うるう年(_年),
        ある年の一月一日の曜日は(_年,_曜日ならび1,_),
        日めくりカレンダ(うるう年,_年,_曜日ならび1,_日めくりカレンダ),
        append(_,[_月/1/_曜日|_],_日めくりカレンダ),!.
ある年・ある月の一日の曜日は(_年,_月,_曜日) :-
        \+(うるう年(_年)),
        ある年の一月一日の曜日は(_年,_曜日ならび1,_),
        日めくりカレンダ(平年,_年,_曜日ならび1,_日めくりカレンダ),
        append(_,[_月/1/_曜日|_],_日めくりカレンダ),!.

ある年の一月一日の曜日は(_年,_曜日ならび,_曜日) :-
        '2000年1月1日は土曜日である'(_曜日ならびの一).
        ある年の一月一日の曜日は(2000,_年,_曜日ならびの一,_曜日ならび),
        _曜日ならび = [_曜日|_],!.

ある年の一月一日の曜日は(_年,_年,_曜日順ならび,_曜日順ならび) :- !.
ある年の一月一日の曜日は(_N,_年,_曜日順ならび1,_曜日順ならび) :-
        _年 >= 2000,
        うるう年(_N),
        ならびの回転(左方向,366,_曜日順ならび1,_曜日順ならび2),
        _N2 is _N + 1,
        ある年の一月一日の曜日は(_N2,_年,_曜日順ならび2,_曜日順ならび).
ある年の一月一日の曜日は(_N,_年,_曜日順ならび1,_曜日順ならび) :-
        _年 >= 2000,
        \+(うるう年(_N)),
        ならびの回転(左方向,365,_曜日順ならび1,_曜日順ならび2),
        _N2 is _N + 1,
        ある年の一月一日の曜日は(_N2,_年,_曜日順ならび2,_曜日順ならび).
ある年の一月一日の曜日は(_N,_年,_曜日順ならび1,_曜日順ならび) :-
        _年 < 2000,
        _N1 is _N - 1,
        うるう年(_N1),
        ならびの回転(右方向,366,_曜日順ならび1,_曜日順ならび2),
        ある年の一月一日の曜日は(_N1,_年,_曜日順ならび2,_曜日順ならび).
ある年の一月一日の曜日は(_N,_年,_曜日順ならび1,_曜日順ならび) :-
        _年 < 2000,
        _N1 is _N - 1,
        \+(うるう年(_N1)),
        ならびの回転(右方向,365,_曜日順ならび1,_曜日順ならび2),
        ある年の一月一日の曜日は(_N1,_年,_曜日順ならび2,_曜日順ならび).

'2000年1月1日は土曜日である'([土,日,月,火,水,木,金]).

月日数ならび(平年,[1:31,2:28,3:31,4:30,5:31,6:30,7:31,8:31,9:30,10:31,11:30,12:31]).
月日数ならび(うるう年,[1:31,2:29,3:31,4:30,5:31,6:30,7:31,8:31,9:30,10:31,11:30,12:31]).

日めくりカレンダの生成(平年,_曜日ならび,_日めくりカレンダ) :-
        月日数ならび(平年,L),
        日めくりカレンダの生成(L,_曜日ならび,_日めくりカレンダの一),
        flat(_日めくりカレンダの一,_日めくりカレンダ).
日めくりカレンダの生成(うるう年,_曜日ならび,_日めくりカレンダ) :-
        月日数ならび(うるう年,L),
        日めくりカレンダの生成(L,_曜日ならび,_日めくりカレンダの一),
        flat(_日めくりカレンダの一,_日めくりカレンダ).

日めくりカレンダの生成([],_,[]) :- !.
日めくりカレンダの生成([[_月:_末日]|R1],_曜日ならび1,[L|R2]) :-
        一ヶ月分の日めくりを生成(1,_末日,_曜日ならび1,_曜日ならび2,L),
        日めくりカレンダの生成(R1,_曜日ならび2,R2).

一ヶ月分の日めくりを生成(N,_末日,_月,_曜日ならび,_曜日ならび,[]) :- N > _末日,!.
一ヶ月分の日めくりを生成(N,_末日,_月,[_曜日|R4],_曜日ならび,[_月/N/_曜日|R]) :-
        N2 is N + 1,
        ならびの回転(左方向,1,[_曜日|R4],_曜日ならび2),
        一ヶ月分の日めくりを生成(N2,_末日,_月,_曜日ならび2,_曜日ならび,R).

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