一个日历有关问题的C语言,C++(boost),python,Javascript,Java和Matlab的实现

一个日历问题的C语言,C++(boost),python,Javascript,Java和Matlab的实现

今天看到一个很有趣的题目,题目描述如下:

根据下列信息计算在1901年1月1日至2000年12月31日间共有多少个星期天落在每月的第一天上?
a)  1900.1.1是星期一
b)  1月,3月,5月,7月,8月,10月和12月是31天
c)  4月,6月,9月和11月是30天
d)  2月是28天,在闰年是29天
e)  公元年数能被4整除且又不能被100整除是闰年
f)  能直接被400整除也是闰年


以下是C语言实现版本:

#include <stdio.h>
#include <stdbool.h>

bool isLeapYear(int year);

// start is the weekday of 1st, January
// return the num of the first day of each month
// is Sunday.
// the start will change into the next year
int getYearNum(int* start, int year);

// Num of days of each month
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int leapdays[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int main(void)
{
	int sum = 0;
	int start = 1901;
	int end = 2000;
	int startWeek = 1;
	int startYear = 1900;
	int i;

	for (i = 1; i < 13; ++i)
		days[i] += days[i - 1];
	for (i = 1; i < 13; ++i)
		leapdays[i] += leapdays[i - 1];

	for (i = startYear; i < start; ++i)
		getYearNum(&startWeek, i);

	for (i = start; i <= end; ++i)
		sum += getYearNum(&startWeek, i);

	printf("%d\n", sum);

	return 0;
}

bool isLeapYear(int year)
{
	if (year % 4 == 0 && year % 100 != 0)
		return true;
	else if (year % 400 == 0)
		return true;
	return false;
}

int getYearNum(int* start, int year)
{
	int i;
	int count = 0;
	int yeardays;

	if (isLeapYear(year))
	{
		yeardays = 366;
		for (i = 0; i < 12; ++i)
			if ((leapdays[i] % 7 + *start)%7 == 0)
				++count;
	} else
	{
		yeardays = 365;
		for (i = 0; i < 12; ++i)
			if ((days[i] % 7 + *start)%7 == 0)
				++count;
	}
	*start = (yeardays % 7 + *start)%7;
	return count;
}


下面是强大的C++和boost程序库的舞台:

#include <boost/date_time/gregorian/gregorian.hpp>
#include <iostream>

using namespace std;
using namespace boost::gregorian;

int main()
{
	int startYear, endYear;
	cout << "Please input the start year: ";
	cin >> startYear;

	cout << "Please input the end year: ";
	cin >> endYear;

	date stdt(startYear, 1, 1);
	date eddt(endYear + 1, 1, 1);
	month_iterator m_iter(stdt);

	int sum = 0;
	while (m_iter != eddt)
	{
		if (m_iter->day_of_week() == 0)
		{
			cout << *m_iter << " is Sunday" << endl;
			++sum;
		}
		++m_iter;
	}
	cout << "There are " << sum
		 << " Sundays are the 1st day of month between "
		 << stdt << " and " << eddt - date_duration(1) << endl;

	return 0;
}

效果如下:
一个日历有关问题的C语言,C++(boost),python,Javascript,Java和Matlab的实现


下来是最简单的python:

import calendar
sum = 0
startYear = 1901
endYear = 2000
for year in xrange(startYear, endYear + 1):
	for month in xrange(1, 13):
		if calendar.monthcalendar(year, month)[0].index(1) == 6:
			sum = sum + 1

print sum

最近对于JavaScript的网页脚本有点感兴趣,就试着用JavaScript实现了一下,感觉不错,有可视化和跨平台性:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>问题2的解答:Javascript版本</title>
</head>
<body>
<script type="text/javascript">
	yearTest = /^[1-9]\d{3}$/;
	days = new Array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	leapdays = new Array(0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	for (var i = 1; i < days.length; i++)
		days[i] += days[i - 1];
	for (var i = 1; i < leapdays.length; i++)
		leapdays[i] += leapdays[i - 1];

	sum = 0;

	function isLeap(year)
	{
		if (!yearTest.test(year))
			return false;
		if (year % 4 == 0 && year % 100 != 0)
			return true;
		if (year % 400 == 0)
			return true;
		return false;
	}

	startWeek = 1;
	totalDays = 365;

	function getResultOfYear(year)
	{
		var sum = 0;
		if (isLeap(year))
		{
			totalDays = 366;
			for (var i = 0; i < leapdays.length - 1; i++)
			{
				if ((leapdays[i] % 7 + startWeek) % 7 == 0)
				{
					//alert("year: " + year + " month: " + (i + 1));
					sum++;
				}
			}
			startWeek = (totalDays % 7 + startWeek) % 7;
		}
		else
		{
			totalDays = 365;
			for (var i = 0; i < days.length - 1; i++)
			{
				if ((days[i] % 7 + startWeek) % 7 == 0)
					sum++;
			}
			startWeek = (totalDays % 7 + startWeek) % 7;
		}
		return sum;
	}
	function main()
	{
		var startYear=document.getElementById("startText").value.replace(/(^\s+)|(\s+$)/g,'');
		if (startYear == "" || !yearTest.test(startYear))
		{
			alert("不合法的起始年份!");
			return;
		}
		if (startYear < 1900)
		{
			alert("起始年份必须大于等于1900!");
			return;
		}
		var endYear = document.getElementById("endText").value.replace(/(^\s+)|(\s+$)/g,'');
		if (endYear == "" || !yearTest.test(endYear))
		{
			alert("不合法的终止年份!");
			return;
		}
		if (endYear < startYear)
		{
			alert("终止年份必须大于等于起始年份!");
			return;
		}
		sum = 0;
		startWeek = 1;

		for (i = 1900; i < startYear; i++)
			getResultOfYear(i);
		for (i = startYear; i <= endYear; i++)
			sum += getResultOfYear(i);
		document.getElementById("resultText").innerHTML = "从"
				+ startYear + "年1月1日到" + endYear +
				"年12月23日有<b>" + sum + "</b>个月的1日是周日。";
	}
</script>
	请输入起始年份:
	<input type="text" id="startText" autofocus onkeydown=
	"if(event.keyCode==13){endText.focus()}">
	<br/>
	请输入终止年份:
	<input type="text" id="endText" onkeydown=
	"if(event.keyCode==13){ok.click()}">
	<br/>
	<button id="ok" onclick="main()">确定</button>
	<br/>
	<p id="resultText"></p>
</body>
</html>


JavaScript在手机上的效果如下:

一个日历有关问题的C语言,C++(boost),python,Javascript,Java和Matlab的实现

再看非常严谨的Java程序:

import java.util.Calendar;
import java.util.Scanner;
import java.text.SimpleDateFormat;

public class Question2
{
	static public void main(String[] args)
	{
		int startYear, endYear;
		Scanner sc = new Scanner(System.in);

		System.out.print("Please input start year: ");
		startYear = sc.nextInt();

		System.out.print("Please input end year: ");
		endYear = sc.nextInt();

		int sum = 0;
		Calendar dt = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

		for (int year = startYear; year <= endYear; ++year)
		{
			dt.set(Calendar.YEAR, year);
			for (int month = 1; month < 13; ++month)
			{
				dt.set(Calendar.MONTH, month);
				dt.set(Calendar.DAY_OF_MONTH, 1);
				if (dt.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
				{
					System.out.println(sdf.format(dt.getTime()) + " is Sunday.");
					++sum;
				}
			}
		}
		dt.set(startYear, Calendar.JANUARY, 1);
		System.out.print("There are " + sum + " Sundays are the 1st day of month between " + sdf.format(dt.getTime()));
		dt.set(endYear, Calendar.DECEMBER, 31);
		System.out.println(" to " + sdf.format(dt.getTime()));
	}
}

运行效果如下:

一个日历有关问题的C语言,C++(boost),python,Javascript,Java和Matlab的实现

最后的最后,来一个鬼畜版:Matlab版本:

startYear = input('Please input the start year: ');
endYear = input('Please input the end year: ');

sum = 0;
for year = startYear : endYear
    for month = 1 : 12
        cal = calendar(year, month);
        if cal(1,1) == 1
            sum = sum + 1;
            display([num2str(year) '-' num2str(month) '-1 is Sunday']);
        end
    end
end
display(['There are ' num2str(sum) ...
    ' Sundays are the 1st day of month between ' num2str(startYear)...
    '-1-1 to ' num2str(endYear) '-1-1']);

效果为:

一个日历有关问题的C语言,C++(boost),python,Javascript,Java和Matlab的实现



OK,一个问题,多种语言,各有优劣。同时用多种语言是一种很不错的体验。