このディレクトリの索引

http://pc12.2ch.net/test/read.cgi/tech/1247438792/103
# 【質問テンプレ】 
# [1] 授業単元: C言語演習 
# [2] 問題文(含コード&リンク): http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/9753.txt 
# 2.入力された年月の1日が何曜日かを調べる。
#   曜日のチェックはZellerの公式を使用する。Zellerの公式は、
#   
#   曜日を表す値=(y + [ y / 4 ] - [ y / 100 ] + [ y / 400 ] + [ (( 13 * m ) + 8 ) / 5 ] + d ) % 7
# 
#           ※ 上記の公式中の y は年、 m は月、 d は日を表し、
#             []はその数を越えない最大の整数を表す。(例: [13.6]は13になる)
# 
#   で、曜日を表す値は次のようになっている。
# 
#     日曜日 = 0,   月曜日 = 1,   火曜日 = 2,   水曜日 = 3,
#         
#         木曜日 = 4,   金曜日 = 5,   土曜日 = 6,
# 
#   ※但し、1月と2月は前年の13月14月として計算するものとする。

% (1) 年月の入力

年月入力処理(_年,_月) :-
    年入力処理(_年),
    月入力処理(_月).

% (2) 曜日計算

:- op(450,xfx,が),op(500,xfy,であり),op(600,xfx,ならば),op(450,xfx,は).

'Zellerの公式'(年 が Y であり 月 が M であり 日 が D ならば 曜日を表す値 は (Y + Y // 4 - Y // 100 + Y // 400 + ((( 13 * M ) + 8 ) // 5 ) + D ) mod 7).


曜日計算処理(_年,_月,_日,_曜日) :-
    'Zellerの公式を用いて曜日を得る'(_年,_月,_日,_曜日).

'Zellerの公式を用いて曜日を得る'(_年,_月,_日,_曜日) :-
    'Zellerの公式を用いて曜日を表す値を得る'(_年,_月,_日,_曜日を表す値),
    曜日を表す値(_曜日を表す値,_曜日).

'Zellerの公式を用いて曜日を表す値を得る'(_年,1,_日,_曜日を表す値) :-
    _前年 is _年 - 1,
    'Zellerの公式を用いて曜日を表す値を得る'(_前年,13,_日,_曜日を表す値),!.
'Zellerの公式を用いて曜日を表す値を得る'(_年,2,_日,_曜日を表す値) :-
    _前年 is _年 - 1,
    'Zellerの公式を用いて曜日を表す値を得る'(_前年,14,_日,_曜日を表す値),!.
'Zellerの公式を用いて曜日を表す値を得る'(_年,_月,_日,_曜日を表す値) :-
    _年=Y,_月=M,_日=D,
    'Zellerの公式'(年 が Y であり 月 が M であり 日 が D ならば 曜日を表す値 は _Zellerの公式),
    _曜日を表す値 is _Zellerの公式,!.

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

% (3) カレンダー表示

カレンダー表示 :-
    年月入力処理(_年,_月),
    'Zellerの公式を用いて曜日を表す値を得る'(_年,_月,1,_曜日を表す整数値),
    カレンダー表示データ編集(_年,_月,_曜日を表す整数値,_カレンダー表示文字列ならび),
    要素に空白を挿入して全行表示(_カレンダー表示文字列ならび).
    
カレンダー表示データ編集(_年,_月,_各月1日の曜日を表す整数値,_カレンダー表示文字列ならび) :-
    年月文字列編集処理(_年,_月,_年月文字列),    
    月日数(_年,_月,_月日数),
    findall(S,(between(1,_月日数,N),ヘッドゼロサプレス(2,N,S)),_表示日ならび),
    Length is _月日数 + _各月1日の曜日を表す整数値,
    M is (7 - (Length mod 7)),
    '7個組ならび'(Length,M,_表示日ならび,_7個組ならび),
    見出しならび(_年月文字列,_見出しならび),
    append(_見出しならび,_7個組ならび,_カレンダー表示文字列ならび).

見出しならび(_年月文字列,[[_年月文字列],[日,月,火,水,木,金,土]]).

'7個組ならび'(Length,0,_表示日ならび,_7個組ならび) :-
    length(L0,Length),
    すべての要素が(L0,'  '),
    append(L0,_表示日ならび,L),
    '7個組'(L,_7個組ならび),!.
'7個組ならび'(Length,M,_表示日ならび,_7個組ならび) :-
    not(M=0),
    length(L0,Length),
    すべての要素が(L0,'  '),
    length(L2,M),
    すべての要素が(L2,'  '),
    append(L0,_表示日ならび,L2,L),
    '7個組'(L,_7個組ならび),!.

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

月日数(_年,2,29) :-
    うるう年(_年),!.
月日数(_年,2,28) :-
    not(うるう年(_年)),!.
月日数(_,_月,30) :-
    member(_月,[4,6,9,11]).
月日数(_,_月,31) :-
    member(_月,[1,3,5,7,8,10,12]).

% (4) 基礎述語の定義

行入力(_行) :-
    read_line_to_codes(current_input,_コードならび),
    atom_codes(_行,_コードならび).

年入力処理(_年) :-
    write('表示したいカレンダーは西暦何年 ? '),
    行入力(_行),
    年入力処理の二(_行,_年),
    年入力検査(_年),!.
年入力処理(_年) :- 年入力処理(_年).

年入力処理の二(_行,_年) :-
    atom_number(_行,_年),
    integer(_年),!.
年入力処理の二(_行,_年) :-
    writef('この入力[ %t ]は整数ではありません\n',[_行]),
    fail.

年入力検査(_年) :-
    _年 >= 1583,
    _年 =< 3999,!.    
年入力検査(_年) :-
    writef('この年を表す整数%tは不正です\n',[_年]),
    fail.

月入力処理(_月) :-
    write('月は ? '),
    行入力(_行),
    月入力処理の二(_行,_月),
    月入力検査(_月),!.
月入力処理(_月) :- 月入力処理(_月).

月入力処理の二(_行,_月) :-
    atom_number(_行,_月),
    integer(_月),!.
月入力処理の二(_行,_月) :-
    writef('この入力[ %t ]は整数ではありません\n',[_行]),
    fail.    

月入力検査(_月) :-
    _月 >= 1,
    _月 =< 12,!.    
月入力検査(_月) :-
    writef('この月を表す整数%tは不正です\n',[_月]),
    fail.

日付文字列編集処理(_年,_月,_日,_日付文字列) :-
    ヘッドゼロサプライ(2,_年,_年文字列),
    ヘッドゼロサプライ(2,_月,_月文字列),
    ヘッドゼロサプライ(2,_日,_日文字列),
    concat_atom([_年文字列,_月文字列,_日文字列],_日付文字列).

年月文字列編集処理(_年,_月,_年月文字列) :-
    ヘッドゼロサプライ(2,_年,_年文字列),
    ヘッドゼロサプライ(2,_月,_月文字列),
    concat_atom([_年文字列,_月文字列],_年月文字列).

ヘッドゼロサプライ(N桁,_整数,_ヘッドゼロ整数文字列) :-
    number_chars(_整数,_数字ならび),
    ヘッドゼロサプライ_1(N桁,_数字ならび,_ヘッドゼロ整数文字ならび),
    concat_atom(_ヘッドゼロ整数文字ならび,_ヘッドゼロ整数文字列),!. 

ヘッドゼロサプライ_1(N桁,L,L) :-
    length(L,N桁),!.
ヘッドゼロサプライ_1(N桁,L,['0'|R]) :-
    M桁 is N桁 - 1,
    ヘッドゼロサプライ_1(M桁,L,R).

ヘッドゼロサプレス(N桁,_整数,_ヘッド空白整数文字列) :-
    number_chars(_整数,_数字ならび),
    ヘッドゼロサプレス_1(N桁,_数字ならび,_ヘッド空白整数文字ならび),
    concat_atom(_ヘッド空白整数文字ならび,_ヘッド空白整数文字列),!. 

ヘッドゼロサプレス_1(N桁,L,L) :-
    length(L,N桁),!.
ヘッドゼロサプレス_1(N桁,L,[' '|R]) :-
    M桁 is N桁 - 1,
    ヘッドゼロサプレス_1(M桁,L,R).

要素に空白を挿入して全行表示([]) :- !.
要素に空白を挿入して全行表示([L|R]) :-
    concat_atom(L,' ',_表示行),
    writef('%w\n',[_表示行]),
    要素に空白を挿入して全行表示(R).

すべての要素が([],_).
すべての要素が([V|R],V) :-
    すべての要素が(R,V).

'7個組'([],[]) :- !.
'7個組'([A,B,C,D,E,F,G|R1],[[A,B,C,D,E,F,G]|R2]) :-
       '7個組'(R1,R2).

n個組(N,L,X) :-
    length(X,N),
    append(X,L2,L3),
    append(L1,L3,L),
    length(L1,Len),
    0 is Len mod N.

not(P) :- \+(P).

append([],L1,L2,L) :-
    append(L1,L2,L) .
append([A|R1],L1,L2,[A|R]) :-
    append(R1,L1,L2,R) .

concat_atom([],'') :- !.
concat_atom([A],A) :- !.
concat_atom([A|R],S) :-
    concat_atom(R,S1),
    atom_concat(A,S1,S).

concat_atom([],_,'') :- !.
concat_atom([A],_,A) :- !.
concat_atom([A|R],_区切り文字列,S) :-
    concat_atom(R,_区切り文字列,S1),
    atom_concat(A,_区切り文字列,S2),
    atom_concat(S2,S1,S).