我怎样才能找到13号星期五出现的一年多少次?

时间:2013-11-24 01:15:04

标签: c++ algorithm

就像标题所说的那样,我试图找出第13届星期五在特定年份出现的次数。我必须使用date类,并以某种方式编写代码来解决它。

Date.h

#ifndef DATE_H
#define DATE_H
#include <string>
#include <iostream>
using namespace std;

string Month[] = { "", "January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December" };

int daysInMonth[2][13] = { { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
                           { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
string DOW[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "" };
class Date {
private:
    int *month;
    int *day;
    int *year;
public:
    // constructors
    Date(int month, int day, int year);
    Date(); // default constructor

    Date(Date &other);  // copy constructor
    Date(string mmddyyyy);  // constructor that takes a string as parameter e.g "10/31/2012"

    ~Date();

    // overload assignment operator 

    Date & operator=(Date & rhs);
    Date & operator++();
    Date & operator++(int);
    Date & operator--();
    Date & operator--(int);
    bool operator ==(Date & rhs);
    bool operator != (Date & rhs);
    bool operator > (Date & rhs);
    bool operator < (Date & rhs);

    int operator-(Date & rhs);
    Date & operator+(int);

    // accessors

    int getDay() {
        return *this->day;
    }

    int getMonth() {
        return *this->month;
    }

    int getYear() {
        return *this->year;
    }

    static Date toDate(int doy, int yr) {
        int dayOfMonth = doy;
        int month = 1;
        int isleap = isLeap(yr);

        for (int i = 1; i < 13; i++) {
            int daysThisMonth = daysInMonth[isleap][i];
            if (dayOfMonth <= daysThisMonth) {
                break;
            }
            else {
                month++;
                dayOfMonth -= daysThisMonth;
            }
        }
        return *new Date(month, dayOfMonth, yr);
    }

    // display date in the format of mm/day/year e.g. 10/31/2012
    void display() {
        cout << *this->month << "/" << *this->day << "/" << *this->year;
    }

    // returns true if the given year is a leap year and false otherwise
    static int isLeap(int year) {
        return ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0));
    }

    // returns the day code the the new year day of the given year
    static int get_day_code(int year) {
        return (year + (year - 1) / 4 - (year - 1) / 100
            + (year - 1) / 400) % 7;
    }

    // overloading get_day_code that returns the day code of the specific day
    static int get_day_code(int year, int month, int day) {
        int dayCodeForYear = get_day_code(year);
        Date temp(month, day, year);
        int doy = temp.dayOfYear() - 1;
        int dayCode = (dayCodeForYear + doy) % 7;
        return dayCode;
    }

    int dayOfWeek() { // return the day code of this day
        int dayOfYear = this->dayOfYear() - 1;
        int firstDayOfTheYear = Date::get_day_code(*this->year);
        dayOfYear += firstDayOfTheYear;
        return dayOfYear % 7;
    }

    int dayOfYear() {  // returns the day of the year, eg,  the day of year for Feb 28 is 59.
        int doy = 0;
        int isleap = isLeap(*year);
        for (int i = 1; i < *month; i++) {
            doy += daysInMonth[isleap][i];
        }
        doy += *day;
        return doy;
    }
};

Date::Date(int month, int day, int year) {
    this->month = new int(month);
    this->day = new int(day);
    this->year = new int(year);
}

Date::Date() {
    this->month = new int(1);
    this->day = new int(1);
    this->year = new int(2000);
}

Date::Date(Date &other) {
    this->month = new int(*(other.month));
    this->day = new int(*(other.day));
    this->year = new int(*(other.year));
}

Date::Date(string mmddyyyy) {
    string mm = mmddyyyy.substr(0, 2);
    string dd = mmddyyyy.substr(2, 2);
    string yyyy = mmddyyyy.substr(4, 4);

    this->month = new int(atoi(mm.c_str()));
    this->day = new int(atoi(dd.c_str()));
    this->year = new int(atoi(yyyy.c_str()));
}

Date::~Date() {
    if (month) delete month;
    if (day) delete day;
    if (year) delete year;
}

bool Date::operator == (Date & rhs) {
    return (*year == *(rhs.year) && *month == *(rhs.month) && *day == *(rhs.day));
}

bool Date::operator != (Date & rhs) {
    return !(*this == rhs);
}

bool Date::operator > (Date & rhs) {
    if (*year > *(rhs.year)) return true;
    else if (*year < *(rhs.year)) return false;
    else if (*month > *(rhs.month)) return true;
    else if (*month < *(rhs.month)) return false;
    else if (*day > *(rhs.day)) return true;
    return false;
}

bool Date::operator < (Date & rhs) {
    if (*year < *(rhs.year)) return true;
    else if (*year > *(rhs.year)) return false;
    else if (*month < *(rhs.month)) return true;
    else if (*month > *(rhs.month)) return false;
    else if (*day < *(rhs.day)) return true;
    return false;
}

Date & Date::operator=(Date & rhs) {
    *this->month = *rhs.month;
    *this->day = *rhs.day;
    *this->year = *rhs.year;
    return *this;
}

Date & Date::operator++() {
    Date tmp = *this + 1;
    *this->month = *tmp.month;
    *this->day = *tmp.day;
    *this->year = *tmp.year;
    return *this;
}
Date & Date::operator++(int) {
    Date tmp = *this + 1;
    Date * output = new Date(tmp);
    *this->month = *tmp.month;
    *this->day = *tmp.day;
    *this->year = *tmp.year;
    return *output;
}

Date & Date::operator--() {
    Date tmp = *this + -1;
    *this->month = *tmp.month;
    *this->day = *tmp.day;
    *this->year = *tmp.year;
    return *this;
}

Date & Date::operator--(int) {
    Date tmp = *this + -1;
    Date * output = new Date(tmp);
    *this->month = *tmp.month;
    *this->day = *tmp.day;
    *this->year = *tmp.year;
    return *output;
}

int Date::operator-(Date & rhs) {
    int yearsDiff = *this->year - *rhs.year;
    int daysDiff = this->dayOfYear() - rhs.dayOfYear();
    daysDiff += yearsDiff * 365;
    return daysDiff;
}

Date & Date::operator+(int) {
    int n = 0;
    int doy = dayOfYear();
    int newDoy = doy + n;
    int yearsDiff = newDoy / 365;
    newDoy = newDoy % 365;
    int newYear = *this->year + yearsDiff;
    Date newDate = Date::toDate(newDoy, newYear);
    return *new Date(newDate);
}
#endif

这是我一直在搞乱的代码:

Source.cpp

#include <iostream>
#include <iomanip>
#include "Date.h"

using namespace std;

void iterateMonth(int);
bool isFriday13th();
string dayofweek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "" };
string month[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "" };
//int dayInMonth[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//int dayInMonthLeap[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };


void iterateMonth(int year) {
    int dayCode, month, daysInMonth, day, u;
    bool leapYear;
    cout << year;

    // returns the day on which January 1 of year begins.
    dayCode = Date::getDayCode(year);
    // returns true if year is a leap year, false otherwise
    leapYear = Date::isLeap(year);

    // month is 0 for Jan, 1 for Feb, etc.
    for (month = 1; month <= 12; month++)
    {
        switch (month)
        {
        case 1:
            cout << "\n\nJanuary\n";
            daysInMonth = 31;
            break;
        case 2:
            cout << "\n\nFebruary\n";
            if (leapYear)
                daysInMonth = 29;
            else
                daysInMonth = 28;
            break;
        case 3:
            cout << "\n\nMarch\n";
            daysInMonth = 31;
            break;
        case 4:
            cout << "\n\nApril\n";
            daysInMonth = 30;
            break;
        case 5:
            cout << "\n\nMay\n";
            daysInMonth = 31;
            break;
        case 6:
            cout << "\n\nJune\n";
            daysInMonth = 30;
            break;
        case 7:
            cout << "\n\nJuly\n";
            daysInMonth = 31;
            break;
        case 8:
            cout << "\n\nAugust\n";
            daysInMonth = 31;
            break;
        case 9:
            cout << "\n\nSeptember\n";
            daysInMonth = 30;
            break;
        case 10:
            cout << "\n\nOctober\n";
            daysInMonth = 31;
            break;
        case 11:
            cout << "\n\nNovember\n";
            daysInMonth = 30;
            break;
        case 12:
            cout << "\n\nDecember\n";
            daysInMonth = 31;
            break;
        }
        //cout << "\n\nSun  Mon  Tue  Wed  Thu  Fri  Sat\n";
        for (int i = 0; i < (sizeof(dayofweek) / sizeof(dayofweek[0])); i++)
        {
            cout << dayofweek[i] << "  ";
        }
        cout << endl;
        for (day = 1; day <= dayCode * 5; day++)
        {
            cout << " ";
        }
        for (day = 1; day <= daysInMonth; day++)
        {
            cout << setw(3) << day;
            if ((day + dayCode) % 7 > 0)
            {
                cout << "  ";
            }
            else
                cout << endl;
        }
        dayCode = (dayCode + daysInMonth) % 7;
   }
}
//bool isFriday13th() {
//
//}

int main() {
    int year;
    //cout << "Please enter a year: ";
    cout << "Final ";
    cin >> year;
    iterateMonth(year);
}

我从某人那里得到的一个想法是在1月13日创建一个Date对象,使用dayOfWeek方法检查是否是星期五,如果没有,则递增直到我到达星期五,然后跳到前方7并使用getDay检查它是否为13.我用这个尝试了这个:

Date tmp(1, 13, year);
int dc = tmp.dayOfWeek(); // return day code

tmp.display();
cout << endl;
++tmp;
tmp.display();
cout << endl;

我预计tmp.display();行显示2013年1月13日(将2013年作为年份),它确实如此,但++tmp行给出了相同的结果。我还以为我必须以某种方式找到与星期五相对应的日期代码(现在dc为0),但我无法弄明白。

此外,另一篇与同一问题有关的帖子说,每个星期日开始的月份都会在星期五13号,所以我试着想一想如何实现这个。也许在第一个for循环(switch语句之上)的某处,我可以检查if (firstDay = Sunday) { cout << "Friday13th exists in " << month << endl; }

之类的内容

那是一种可怕的伪代码,但这是我的想法。有人有想法吗?任何帮助将不胜感激,并提前感谢您。

2 个答案:

答案 0 :(得分:3)

嗯......对于初学者 - 如果您使用Date标题和functions包含在内,<ctime>课程会更容易。

其次 - 你有一个重载函数:int get_day_code(int year, int month, int day)。如果它做了它应该做的事情(或更像是:描述的内容),为了检查一年中第13次星期五的次数,你可能会这样做:

int howManyFridays = 0;
for(int i=0;i<12;i++)
   if(get_day_code(year,i,13)==CODE_FOR_FRIDAY) howManyFridays++;
return howManyFridays;

答案 1 :(得分:2)

你可以这样做,而无需对一年中某一天的函数进行大量调用。如果你知道1月份第一个星期天的日期,那就没什么了不起的。只是一些基本的数学。

2013年,1月的第一个星期日是第6个星期日。所以13日是星期天。我们知道,如果1月的第一个星期日是第6个,那么2月的第一个星期日就是第3个星期日。为13日增加10天。那是星期三。

我怎么知道二月的第一个星期天是第三个?因为这就是日历的工作方式。如果您参加1月份第一个星期天的日期,请添加4和mod 7,这将为您提供2月份第一个星期日的日期。日历是固定的;在1月的第一个星期日,您可以使用模7算法轻松计算任意月份的第一个星期日。

补偿是:

Normal Year: 0 4 4 1 6 3 1 5 2 0 4 2 
Leap Year:   0 4 3 0 5 2 0 4 1 6 3 1 

如果你想知道星期五在13日的几个月,那么下一个星期日是15日,这意味着该月的第一个星期日必须是第一个星期日。

根据上表,如果1月的第一个星期日是第1个星期,那么在正常年份,你将在星期五13日:1月和10月有两个月。如果是闰年,那么你将有1月,4月和7月。今年的第一个星期天是第6个星期日,所以你需要几个月的偏差为2个。所以9月和12月。

如果月份偏移量加上1月份第一个星期日的日期等于8,则该月份的星期五为13日。

我前段时间用这个作为记忆法。有关详细说明,请参阅Now what day is that?