末日演算法
末日演算法
2199年7月2日是星期幾?根據日期計算當天是星期幾是一個有趣的問題,通常的思路是:選擇任意一天作為我們計算的基礎,比如2018年8月5日星期日,然後計算出目標日期與基礎日期相差多少天,再推算目標日期是星期幾。在沒有遇見末日演算法之前,我大概不會深入思考這個問題,然後按照上述思路草草解決。但是末日演算法給我們提供了一種新的思路或者說優化了前述的演算法。
末日演算法假設每一年2月的最後一天是末日,因此每一年的3月7日,4月4日,5月9日,6月6日,7月11日,8月8日,9月5日,10月10日,11月7日,12月12日的星期必然和末日的星期相同,因為這些日期和末日相差的天數正好是7的倍數。除此之外,因為平年一年365天,閏年一年366天,所以每過一個平年,末日的星期數加1,每過一個閏年,末日的星期數加2(365 % 7 = 1, 366 % 7 = 2)。這樣一來,只要我們知道某一年的末日是星期幾,就可以按照末日演算法的思路快速地計算出目標日期是星期幾。
雖然末日演算法最後還是要計算時間差,但是它極大地節省了計算量,也許這點計算量在現今的計算環境下算不了什麼,但它讓我看到了有意思的想法,如果我沒有遇見末日演算法,我可能不會繼續深入思考這個問題,程式設計的祕密不僅僅是機械地解決問題,更在於理解邏輯和生活的本質。
const weekList = [
'星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'
];
const doomBase = {
year : 2000,
week : 2
};
const searchMap = {
'3' : 7,
'4' : 4,
'5' : 9,
'6' : 6,
'7' : 11,
'8' : 8,
'9' : 5,
'10' : 10,
'11' : 7,
'12' : 12
};
function isLeapYear( year ) {
return ( year % 4 === 0 && year % 100 !== 0 ) || year % 400 === 0;
}
function positiveModulo( a, b ) {
let result;
result = a % b;
if ( result < 0 ) {
result += b;
}
return result;
}
function getDoomDay( year ) {
let i, result;
result = doomBase.week;
if ( year < doomBase.year ) {
for ( i = doomBase.year - 1; i >= year; i-- ) {
result--;
if ( isLeapYear( i + 1 ) ) {
result--;
}
}
} else {
for ( i = doomBase.year + 1; i <= year; i++ ) {
result++;
if ( isLeapYear( i ) ) {
result++;
}
}
}
result = positiveModulo( result, 7 );
return result;
}
function getWeek( year, month, day ) {
let offset, result;
const doomDay = getDoomDay( year );
if ( month < 3 ) {
if ( isLeapYear( year ) ) {
offset = day - 29 - ( 2 - month ) * 31;
} else {
offset = day - 28 - ( 2 - month ) * 31;
}
} else {
offset = day - searchMap[ month ];
}
result = doomDay + offset;
result = positiveModulo( result, 7 );
return result;
}
function isValidateDate( year, month, day ) {
let result;
result = true;
const dayCountMap = {
'1' : 31,
'3' : 31,
'4' : 30,
'5' : 31,
'6' : 30,
'7' : 31,
'8' : 31,
'9' : 30,
'10' : 31,
'11' : 30,
'12' : 31
};
dayCountMap[ '2' ] = isLeapYear( year ) ? 29 : 28;
if ( month < 1 || month > 12 ) {
result = false;
}
if ( day > dayCountMap[ month ] ) {
result = false;
}
return result;
}
function getDateString( year, month, day ) {
return year + '年' + month + '月' + day + '日';
}
const testData = [
[ 2199, 7, 2 ],
[ 1994, 7, 5 ],
[ 1994, 5, 27 ],
[ 1994, 2, 28 ],
[ 1994, 1, 1 ],
[ 1994, 1, 31 ],
[ 1994, 2, 1 ],
[ 1994, 0, 1 ],
[ 1994, 2, 29 ]
];
const testFunction = () => {
testData.map( ( item ) => {
if ( !isValidateDate( ...item ) ) {
console.log( getDateString( ...item ) + '不是合法的日期!' );
} else {
console.log(
getDateString( ...item ) + '是' + weekList[ getWeek( ...item ) ]
);
}
} );
};
testFunction();
相關文章
- 末日生存手冊:從何為末日談起
- 末日生存策略手遊大作 《末日進化》7月23日首發!
- 潛力釋放的末日生存題材:玩末日生存的人,都在玩什麼?
- 科幻作家是如何想象核末日的?
- 「央視新聞」末日【】wopieury《手機搜狐網》
- Collapse OS:為世界末日建立的作業系統作業系統
- 《王牌戰爭:文明重啟》末日生存玩法今日上線!
- C#中得到每週,每月,每季,每年的年初末日期C#
- 有人就有希望,末日生存遊戲《阿瑞斯病毒2》今日上線!遊戲
- 獨立遊戲佳作《孤帆遠航》:跳出“死亡”的“末日擱淺”遊戲
- 當廣告界說“IDFA末日”時,說的是啥?(科普篇)
- 連線末日世界?《雛蜂:深淵天使》預約正式開啟
- 美國末日的劇情為什麼有這麼強的代入感?
- 人工智慧是攝影的未來還是攝影技術的末日?人工智慧
- 《守望先鋒》中的末日鐵拳是怎麼摧毀玩家體驗的?
- Max:從Abi到末日餘暉,我和莉莉絲都經歷了什麼
- 生存末日類遊戲:逃離喪屍島Dysmantle for Mac 中文直裝版 附 dlc遊戲Mac
- “加密世界末日”即將到來!激進監管推動“逃生潮”湧起!加密
- 張志磊代言末日策略手遊《荒野迷城》,遊戲內版本今日上線!遊戲
- 可聯機!末日生存單機遊戲《阿瑞斯病毒2》8月8日上線!遊戲
- Sensor Tower:2021上半年末日生存手遊全球吸金超過11億美元
- Steam 94%好評,阿里悄悄上架了一款喪屍末日生存射擊遊戲阿里遊戲
- 主打體素風爽快射擊動作遊戲,《ANNIE: Last Hope》末日下的追逐遊戲AST
- “末日博士”魯比尼列出十大理由警告:2020年將爆發金融危機
- 胡景暉:因鏈家老闆施壓 我被談了4小時像末日審判
- 一場空前躁動的末日狂歡儀式過後,這個遊戲“重啟”了遊戲
- 末日生存題材2年時收入激增167%:廠商在海外投放側都做了什麼?
- 末日逼近百度雲(完整共享)網盤完結版【1280P中英雙字.
- Intuit Credit Karma:調查顯示27%美國消費者正在進行“末日消費”現象UI
- 突破重圍殺回免費榜TOP10,《明日之後》如何領跑末日生存品類
- 莉莉絲最新大作《末日餘暉》首曝CG,一手美術製作和幕後搶先看
- 一起末日生存!蓋世小雞G6手柄與《明日之後》官宣合作
- 上半年末日生存手遊全球吸金超11億美元,成收入最高的手遊題材
- 收入曾排國內前五,這家公司時隔3年又做了一款末日生存SLG
- 末日生存敘事表達母子情感,《甦醒之路》能帶來創新遊戲體驗嗎?遊戲
- 莉莉絲新作《末日餘暉》全球首曝,滿足你對射擊遊戲的一切想象!遊戲
- 龍創悅動iOS月收入排國內第九,“末日生存類”手游到底有多掙錢?iOS
- 金山遊戲H1營收14.8億元;H1末日生存手遊吸金超11億美元遊戲營收