ソフトウエア開発におけるアルゴリズムの重要性が増している。指定した年月のカレンダーを表示する「万年カレンダー」の作り方を通してアルゴリズムを学んでいこう。
万年カレンダーは完成しましたが、ここで終わりにしたら、あまり楽しくありません。アルゴリズムの醍醐味は、一度考えたアルゴリズムを改良して、より効率的にすることにあるからです。現状のday_of_week関数(引数で指定された年月の1日が何曜日かを返す関数)は、西暦1年1月1日からの経過日数を、繰り返し処理で集計して求めています。これを1つの計算式で求めるように改良してみましょう。
1つの計算式で経過日数を求める
経過日数を求める年月日を、year、month、dayとすると、経過日数は、以下のように「yearの1年前の末日までの日数」「monthの1カ月前の末日までの日数」「dayの日数」の3つを足す計算式で求められます。
「yearの1年前の末日までの日数」と「monthの1カ月前の末日までの日数」を求める計算式を考えてみましょう。「dayの日数」は、dayの値を足すだけなので考える必要はありません。
まず、「yearの1年前の末日までの日数」は、うるう年を考慮しなければ、365*(year - 1)なので、それにうるう年の回数分の日数を足せば求められます。
year // 4を足せば*4、「原則として、西暦が4で割り切れる年は、うるう年である」の日数を足せます。
year // 100を引けば、「ただし、原則として、西暦が100で割り切れる年は、うるう年ではない」の日数を引けます。
year // 400を足せば、「ただし、西暦が400で割り切れる年は、絶対にうるう年である」を足せます。
したがって、「yearの1年前の末日までの日数」は、以下の計算式で求められます。
次に、「monthの1カ月前の末日までの日数」を求める計算式を得るには、かなり工夫が必要になります。結果を先に示すと、以下の計算式になります。