末日演算法
末日演算法
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();
相關文章
- 從資料結構+演算法分析ORM的末日資料結構演算法ORM
- 末日生存策略手遊大作 《末日進化》7月23日首發!
- 2015:巨型 JavaScript 框架的末日JavaScript框架
- 獨立遊戲佳作《孤帆遠航》:跳出“死亡”的“末日擱淺”遊戲
- Flash末日將近:谷歌明年停運Flash顯示廣告谷歌
- 美國國防部否認能源行業“網路末日論”行業
- C#中得到每週,每月,每季,每年的年初末日期C#
- Collapse OS:為世界末日建立的作業系統作業系統
- 移動網際網路時代:騰訊的盛宴還是末日?
- 連線末日世界?《雛蜂:深淵天使》預約正式開啟
- JavaZone2013年度大片《Java末日》預告片Java
- 移動網際網路,聊天類應用的盛宴還是末日?
- Steam 94%好評,阿里悄悄上架了一款喪屍末日生存射擊遊戲阿里遊戲
- 生存末日類遊戲:逃離喪屍島Dysmantle for Mac 中文直裝版 附 dlc遊戲Mac
- 人工智慧是攝影的未來還是攝影技術的末日?人工智慧
- PS教程:手把手教你建立科幻感超強的世界末日場景
- 主打體素風爽快射擊動作遊戲,《ANNIE: Last Hope》末日下的追逐遊戲AST
- “加密世界末日”即將到來!激進監管推動“逃生潮”湧起!加密
- 一場空前躁動的末日狂歡儀式過後,這個遊戲“重啟”了遊戲
- 莉莉絲新作《末日餘暉》全球首曝,滿足你對射擊遊戲的一切想象!遊戲
- 末日生存敘事表達母子情感,《甦醒之路》能帶來創新遊戲體驗嗎?遊戲
- 突破重圍殺回免費榜TOP10,《明日之後》如何領跑末日生存品類
- 金山遊戲H1營收14.8億元;H1末日生存手遊吸金超11億美元遊戲營收
- ABAP日期函式(求月末日,第幾周,search help 只顯示年月) 使用方法例項函式
- 龍創悅動iOS月收入排國內第九,“末日生存類”手游到底有多掙錢?iOS
- 互動敘事獨立遊戲《大洪水的故事》製作人採訪:末日選擇下的心理拷問遊戲
- 分析如何用金融學的知識促進修真世界、末日世界、遊戲世界等世界的社會進步遊戲
- 2020年6月成功出海的中國手遊TOP30:末日生存、三國題材收入領漲
- “拯救末日”大家族再添一員,軍武擬人戰略手遊《灰燼戰線》全平臺公測開啟
- 【演算法】KMP演算法演算法KMP
- 【JAVA演算法】圖論演算法 -- Dijkstra演算法Java演算法圖論
- 演算法(2)KMP演算法演算法KMP
- 【演算法】遞迴演算法演算法遞迴
- 演算法題:洗牌演算法演算法
- [演算法之回溯演算法]演算法
- Manacher演算法、KMP演算法演算法KMP
- 【演算法】KMP演算法解析演算法KMP
- 介面限流演算法:漏桶演算法&令牌桶演算法演算法