-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproblem19.cpp
More file actions
131 lines (116 loc) · 2.48 KB
/
problem19.cpp
File metadata and controls
131 lines (116 loc) · 2.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
* This is one of the problems that don't require much math, just
* some logical thinking. I've tried to solve it in a readable way.
* The speed gain of a more efficient, but less readable way would not be
* noticable.
*/
#include <iostream>
#include <unordered_map>
using Year = unsigned int;
using Day = unsigned int;
enum Month {
Jan = 1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
};
static bool leapYear(Year y)
{
if (y % 4 != 0)
return false;
if (y % 100 != 0)
return true;
if (y % 400 != 0)
return false;
return true;
}
class Date {
/*
* Day is not really for the number of days, but it enables type-safe
* comparison whether a day has overflowed.
*/
static std::unordered_map<Month, Day> days;
static bool leapYear(Year y)
{
if (y % 4 != 0)
return false;
if (y % 100 != 0)
return true;
if (y % 400 != 0)
return false;
return true;
}
public:
bool leap;
Day d;
Month m;
Year y;
Date(Day d, Month m, Year y): d{d}, m{m}, y{y}, leap{leapYear(y)} { }
/*
* I use this for every arithmetic operation. Inefficient, but the
* difference is negligible.
*/
Date &operator++()
{
Day dayLimit = days[m] + (m == Feb && leap ? 1 : 0);
if (d + 1 > dayLimit) { // if last day of month
d = 1;
if (m == Dec) { // if last month of year
++y;
leap = leapYear(y);
m = Jan;
} else {
m = static_cast<Month>(m + 1);
}
} else {
++d;
}
return *this;
}
bool operator<(const Date &date)
{
if (y < date.y)
return true;
if (y == date.y) {
if (m < date.m)
return true;
if (m == date.m) {
if (d < date.d)
return true;
}
}
return false;
}
};
std::unordered_map<Month, unsigned int> Date::days {
{ Jan, 31 },
{ Feb, 28 },
{ Mar, 31 },
{ Apr, 30 },
{ May, 31 },
{ Jun, 30 },
{ Jul, 31 },
{ Aug, 31 },
{ Sep, 30 },
{ Oct, 31 },
{ Nov, 30 },
{ Dec, 31 }
};
/* In mm/dd/yyyy format. */
std::ostream &operator<<(std::ostream &os, const Date &d)
{
os << d.m << '/' << d.d << '/' << d.y;
}
int main()
{
/*
* 1900 is no leap year, so it had 365 days. If 1 Jan 1900 was a Monday
* and we enumerate the weekdays from 0 to 6, 366 % 7 gives us the weekday.
* 366 because 1 Jan 1901 is one day after the last of 1900, i.e., it's
* 366 days from 1 Jan 1900 till then.
*/
unsigned int i = 0;
unsigned int weekday = 366 % 7;
for (Date d{1, Jan, 1901}; d < Date{1, Jan, 2001}; ++d, ++weekday) {
if (d.d == 1 && weekday % 7 == 6)
++i;
}
std::cout << i << std::endl;
}