Friday the 13th(笑)

グレゴリオ暦において。
2000年1月1日から2399年12月31日までの400年、閏年*1も考えて

400(年)*365(日)+(100-4+1)(日)=146097(日)
146097(日)/7(日)=20871(週)

よって400年分の日数は7で割り切れるので、400年後の同月同日の曜日は一致する。
1605年のカレンダを持っている人は見てみましょう。今年のカレンダを取っておくと2405年にまた使えますよ。(笑)
起点年を2000年(閏年)として、当日は土曜なので、起点を2000年1月0日(=1999年12月31日)の金曜+1=土曜とする。(enumで日曜=0〜土曜=6)
100年毎に起点を更新するが、閏年以外の起点は当年1月0日(=前年12月31日)の曜日になるので注意(switch(i)で0、100〜に分けている意味)
曜日が月を経る度にズレていく。1月を起点としているのでズレは0。1月は31日なので2月に起こるズレは31%7=3・・・と求めていく。(#define)

#include<stdio.h>
#define JAN 0
#define FEB 3
#define MAR 3
#define APL 6
#define MAY 1
#define JUN 4
#define JUL 6
#define AUG 2
#define SEP 5
#define OCT 0
#define NOV 3
#define DEC 5
enum {SUN, MON, TUE, WED, THU, FRI, SAT};
int main()
{
 int start = 0;   /* 起点曜日用 */
 int data = 0;    /* 曜日判別用 */
 int fri_13 = 0;  /* 13日の金曜日カウント用 */
 int i, j;        /* i:2000年からの経過年  j:月 */
 int tmp = 0;     /* 閏年カウント用 */
 for(i = 0; i < 400; i++) {
  switch(i) {
   case 0   : start = SAT; tmp = 0; break;  /* 2000〜2099年代用起点曜日 */
   case 100 : start = THU; tmp = 0; break;  /* 2100〜2199年代用起点曜日 */
   case 200 : start = TUE; tmp = 0; break;  /* 2200〜2299年代用起点曜日 */
   case 300 : start = SUN; tmp = 0; break;  /* 2300〜2399年代用起点曜日 */
   default  : tmp = i / 4; break;
  }
  for(j = 1; j < 13; j++) {
   switch(j) {
    case 1 : if(((i % 4 == 0)&&(i % 100 != 0))||(i % 400 == 0)) {
        data = start + tmp + i + JAN + 13 - 1;
       }else {
        data = start + tmp + i + JAN + 13;
       }
       break;
    case 2 : if(((i % 4 == 0)&&(i % 100 != 0))||(i % 400 == 0)) {
        data = start + tmp + i + FEB + 13 - 1;
       }else {
        data = start + tmp + i + FEB + 13;
       }
       break;
    case 3 : data = start + tmp + i + MAY + 13; break;
    case 4 : data = start + tmp + i + APL + 13; break;
    case 5 : data = start + tmp + i + MAY + 13; break;
    case 6 : data = start + tmp + i + JUN + 13; break;
    case 7 : data = start + tmp + i + JUL + 13; break;
    case 8 : data = start + tmp + i + AUG + 13; break;
    case 9 : data = start + tmp + i + SEP + 13; break;
    case 10: data = start + tmp + i + OCT + 13; break;
    case 11: data = start + tmp + i + NOV + 13; break;
    case 12: data = start + tmp + i + DEC + 13; break;
   }
   data %= 7;
   if(data == FRI) {
    fri_13++;
   }
  }
 }
 printf("Friday the 13th - %d times in 400 years(2000-2399)\n", fri_13);
 printf("%f\n", (float)fri_13 / (400 * 12));
}
Friday the 13th - 688 times in 400 years(2000-2399)
0.143333

片手間なんで間違ってるかも(言い訳(笑))。
switch(j)のcase 1、case 2におけるifは閏年の1・2月は閏日の影響を受けていないため。
つまり400(年)*12(ヶ月)=4800(ヶ月)の中で13日が金曜日になる月は688個ある。
割合は688/4800=0.14333・・・>0.14285・・・=1/7。7ヶ月に1度は「13日の金曜日」が来るということです。

  • -

こういう事を求めたがるのって、中学生の頃がピークじゃないかな。何となく周りで騒いでる奴らが馬鹿に見えたりして(笑)。
こういう事を一瞬でも気にした人は敏感というか臆病というか理系というか。気付かずに騒いでる人達よりは優秀だと思います。

  • -

もっと上手い説明がありました。
参考:yoshik's home/Mathematics(“ú•t‚ð•·‚¢‚Ä—j“ú‚ð“–‚Ä‚é•û–@)

*1:西暦が4で割り切れるなら閏年
ただし100で割り切れるなら平年
ただし400で割り切れるなら閏年