C++で曜日を求める方法|ツェラーの公式(Zeller's Algorithm)を徹底解説
はじめに
「日付(日・月・年)が与えられたとき、その日が何曜日なのかを求めたい」——プログラミングではよくある課題です。これを解決するのがツェラーの公式(Zeller's Algorithm)です。本記事では、ツェラーの公式の計算方法と、C++での実装例をわかりやすく解説します。
ツェラーの公式とは
ツェラーの公式を用いて曜日を求める計算式は以下の通りです。
w = (d + ⌊13(m+1)/5⌋ + y + ⌊y/4⌋ + ⌊c/4⌋ + 5c) mod 7
式に含まれる各変数の意味は次の通りです。
- d − 日付の「日」の部分。
- m − 月のコード。3月から12月まではそのまま3〜12を使用し、1月は13、2月は14として扱います。1月または2月を計算する場合は、年を1減らす点に注意してください。これは、ツェラーの公式が「3月を年初とする暦」を前提としているためです。
- y − 年の下2桁。
- c − 年の上2桁(世紀の部分)。
- w − 曜日を表す結果の値。0なら土曜日、1なら日曜日、6なら金曜日を意味します。
例えば、1997年1月4日の曜日を求めると、出力は「Saturday(土曜日)」となります。
アルゴリズム
zellersAlgorithm(day, month, year)
入力 − 日付(日・月・年)。
出力 − その日の曜日(日曜日〜土曜日)。
Begin
if month > 2, then
mon := month
else
mon := 12 + month
decrease year by 1
y := last two digit of the year
c := first two digit of the year
w := day + floor((13*(mon+1))/5) + y + floor(y/4) + floor(c/4) + 5*c
w := w mod 7
return weekday[w] // weekdayは土曜日から金曜日の順で曜日を保持する
End
C++での実装例
#include <iostream>
#include <cmath>
using namespace std;
string weekday[7] = {"Saturday","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday"};
string zellersAlgorithm(int day, int month, int year){
int mon;
if(month > 2)
mon = month; // 3月〜12月は月コードがそのまま月と一致
else{
mon = (12+month); // 1月と2月の月コードは13と14
year--; // 1月・2月の場合は年を1減らす
}
int y = year % 100; // 年の下2桁
int c = year / 100; // 年の上2桁
int w = (day + floor((13*(mon+1))/5) + y + floor(y/4) + floor(c/4) + (5*c));
w = w % 7;
return weekday[w];
}
int main(){
int day, month, year;
cout << "Enter Day: "; cin >> day;
cout << "Enter Month: "; cin >> month;
cout << "Enter Year: "; cin >> year;
cout << "It was: " << zellersAlgorithm(day, month, year);
}
このコードでは、曜日を格納する配列 weekday を「土曜日から金曜日」の順で定義している点がポイントです。これは、ツェラーの公式の計算結果 w が 0 のとき土曜日になるように設計されているためです。
入力例
(4, 1, 1997)
出力例
Enter Day: 4
Enter Month: 1
Enter Year: 1997
It was: Saturday
まとめ
ツェラーの公式を使えば、複雑なカレンダー処理を行わなくても、日付から曜日を簡単に計算できます。1月と2月を13月・14月として前年の年として扱う点さえ押さえておけば、数行のコードで正確に曜日を求めることができます。ぜひ自分のプロジェクトでも活用してみてください。
-
C++で解く「迷路 II」問題 ― 壁に当たるまで転がるボールの最短距離をBFSで求める
問題概要 空きマスと壁からなる迷路の中にボールがあります。ボールは上・下・左・右のいずれかの方向に転がって空きマスを進むことができますが、壁にぶつかるまで止まることはできません。ボールが停止したときに、初めて次の方向を選ぶことができます。 ボールのスタート位置、目的地、そして迷路そのものが与えられるので、ボールが目的地で停止するまでの最短距離を求めてください。ここでの距離とは、ボールが転がって通過した空きマスの数のことです(スタート位置は含まず、目的地は含みます)。どうしても目的地で停止できない場合は -1 を返します。 迷路は2次元配列で表現されます。1 が壁、0 が空きスペースを意味し、迷
-
C++で解く迷路問題:転がるボールが目的地に止まれるかをBFSで判定する方法
迷路の中にボールがあるとします。迷路には空きスペース(通路)と壁があります。ボールは上下左右のいずれかの方向に転がって空き通路を進むことができますが、壁にぶつかるまで止まりません。ボールが停止したときに、次の方向を選べます。この問題では、ボールの開始位置、目的地、そして迷路そのものが与えられ、「ボールが目的地の位置で停止できるかどうか」を判定する必要があります。迷路は2次元配列で表現され、1は壁、0は空きスペースを意味します。迷路の外周はすべて壁になっています。開始位置と目的地は行・列のインデックス(座標)で与えられます。問題例たとえば、次のような2次元配列で表される迷路を考えてみましょう。0