Monday, April 2, 2012

Rainman


昨天聽Car Talk, 解答上禮拜的 puzzler,puzzler 的問題是:有一個人(Rainman)當你問他幾月幾號,他為什麼可以很快地回答你那一天是星期幾?
我記得小時候上電腦課的時候有遇到一個小朋友也可以做到這件事但是當時問她怎麼弄的,她不肯跟我說。大學的時候看吳兆南說相聲時也看他表演過,覺得一定是有什麼公式,只是從來沒真的花心思去仔細想出來,也沒有去 google 過。
結果今天早上聽到的方法是:使用Anchor days,每年有一些很好記的Anchor day每年的4/4(四月四日),6/6,8/8,10/10,12/12都會是一個禮拜中的同一天,比方說今年4/4是禮拜三,那這幾天都是禮拜三,另外5/9,9/5,7/11(7- Eleven)和11/7也都會是一個禮拜中的同一天。另外二月的最後一天(不管閏年還是非閏年),閏年的一月四日以及非閏年一月三日也都會是同一天。還蠻好玩的。
我想了想該怎麼延伸到某年某月某日是星期幾,也就是問題中加上「某年」。從1900年起,閏年都是規律的逢四就閏[1],所以應該不難算,一年三百六十五天,除以七餘一,若不考慮閏年,每年的同一天的星期幾應該是加一,今年四月四日星期三,那明年四月四號就是星期四。從非閏年到閏年,則要加2。像去年的4/4就是星期一。因此往前(過去)每四年就是減5,mod 7時減5等於加2,每四年加2,也就是往前幾個年到某一閏年就除以2(=*4/2)。比如說已知2012的四月四號是3(代表星期三,假設用1代表星期一,0代表星期天,6 & -1都代表星期六),1980年是閏年,離2012差32年,,(3 + 32 / 2)%7 = 5 則1980年的4/4是星期五,那1980/1/4也是星期五,1980/1/20 - 1980/1/4 = 16, (5 + 16)%7 = 0,則那天就是星期日。有一個實用的資訊應該記起來,那就是2000年是閏年(有2/29)而那年的4/4是星期二。來算算1970/01/01是星期幾。1970/01/01 floor 的閏年是1968,2(2000年4/4星期二)+ (2000 - 1968) / 2 (每四年加二)= 2 + 16 = 18。18 % 7 = 4 則知1968/4/4是星期四,那1969/4/4是星期五,1970/4/4是星期六,1970/1/3星期六,1970/1/1是星期四。
----
[1] 閏年規則:西元年份逢4的倍數閏、100的倍數不閏、400的倍數閏、4000的倍數不閏。例如:西元1992、1996 年等為4的倍數,故為閏年;西元1800、1900、2100年為100的倍數,當年不閏;西元1600、2000、2400年為400的倍數,有閏;而西元4000、8000年為4000的倍數,則不閏。(From wikipedia)