写的很长啊,基本思路是枚举每一年的每一天,然后枚举每一个任务,判断是否符合,一个字符串划分的小技巧是stringstream + getline,很好用,一个坑点是日期、周的英文不区分大小写,好屑。这次模拟思路仍然不完全是自己独立想出来的,还需努力。。。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
map<string, int> monthMapper = {
{"jan", 1},{"feb", 2},{"mar", 3},
{"apr", 4},{"may", 5},{"jun", 6},
{"jul", 7},{"aug", 8},{"sep", 9},
{"oct", 10},{"nov", 11},{"dec", 12}
};
map<string, int> weekMapper = {
{"sun", 0}, {"mon", 1}, {"tue", 2},
{"wed", 3}, {"thu", 4}, {"fri", 5}, {"sat", 6}
};
int daysOfMonth[] = {
0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
struct task {
set<int> minutes;
set<int> hours;
set<int> dayOfMonth;
set<int> month;
set<int> dayOfWeek;
string command;
};
vector<task> tasks;
int n;
string st, ed;
set<string> split(string& str, char spl) {
stringstream ss(str);
string tmp;
set<string> ret;
while (getline(ss, tmp, spl)) {
if (!tmp.empty()) ret.insert(tmp);
}
return ret;
}
string to_lower(const string& s) {
string ret(s);
for (auto& c : ret) {
c = tolower(c);
}
return ret;
}
set<int> resolve(set<string>& inp, int idx) {
set<int> ret;
for (auto& s : inp) {
int li = 0, ri = 0;
auto pos = s.find('-');
if (pos != string::npos) {
string l = s.substr(0, pos);
string r = s.substr(pos + 1);
if (idx < 3) {
li = atoi(l.c_str());
ri = atoi(r.c_str());
} else if (idx == 3) {
if (!isdigit(l[0])) li = monthMapper[to_lower(l)];
else li = atoi(l.c_str());
if (!isdigit(r[0])) ri = monthMapper[to_lower(r)];
else ri = atoi(r.c_str());
} else {
if (!isdigit(l[0])) li = weekMapper[to_lower(l)];
else li = atoi(l.c_str());
if (!isdigit(r[0])) ri = weekMapper[to_lower(r)];
else ri = atoi(r.c_str());
}
for (int i = li; i <= ri; i++) {
ret.insert(i);
}
} else {
if (s == "*") {
ret.insert(10086);
continue;
}
if (idx < 3) {
ret.insert(atoi(s.c_str()));
} else if (idx == 3) {
if (!isdigit(s[0])) {
ret.insert(monthMapper[to_lower(s)]);
} else {
ret.insert(atoi(s.c_str()));
}
} else {
if (!isdigit(s[0])) {
ret.insert(weekMapper[to_lower(s)]);
} else {
ret.insert(atoi(s.c_str()));
}
}
}
}
return ret;
}
void readTask() {
string minutes;
string hours;
string dayOfMonth;
string month;
string dayOfWeek;
string command;
task ne;
cin >> minutes >> hours >> dayOfMonth >> month >> dayOfWeek >> command;
auto a = split(minutes, ',');
ne.minutes = resolve(a, 0);
a = split(hours, ',');
ne.hours = resolve(a, 1);
a = split(dayOfMonth, ',');
ne.dayOfMonth = resolve(a, 2);
a = split(month, ',');
ne.month = resolve(a, 3);
a = split(dayOfWeek, ',');
ne.dayOfWeek = resolve(a, 4);
ne.command = command;
tasks.push_back(ne);
}
bool islunar(int year) {
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
int year;
struct node {
int id;
int year;
int month;
int day;
int hour;
int minute;
string command;
bool operator < (const node& ot) const {
if (year == ot.year) {
if (month == ot.month) {
if (day == ot.day) {
if (hour == ot.hour) {
if (minute == ot.minute) {
if (id == ot.id) {
return command < ot.command;
}
return id < ot.id;
}
return minute < ot.minute;
}
return hour < ot.hour;
}
return day < ot.day;
}
return month < ot.month;
}
return year < ot.year;
}
};
vector<node> nodes;
int getWeekOfDate(int year, int month, int day) {
int wek = 4;
for (int i = 1970; i < year; i++) {
int m = 1, d = 1;
for (; m <= 12; m++) {
if (m == 2) {
if (islunar(i)) {
wek = (wek + 29) % 7;
} else {
wek = (wek + 28) % 7;
}
} else {
wek = (wek + daysOfMonth[m]) % 7;
}
}
}
int m = 1, d = 1;
for (; m < month; m++) {
if (m == 2) {
if (islunar(year)) {
wek = (wek + 29) % 7;
} else {
wek = (wek + 28) % 7;
}
} else {
wek = (wek + daysOfMonth[m]) % 7;
}
}
for (; d < day; d++)
wek = (wek + 1) % 7;
return (wek) % 7;
}
//yyyymmddHHMM
//01234567891011
int between(int year, int month, int day,int hour, int minute) {
int ly = atoi(st.substr(0, 4).c_str());
int ry = atoi(ed.substr(0, 4).c_str());
int lm = atoi(st.substr(4,2).c_str());
int rm = atoi(ed.substr(4,2).c_str());
int ld = atoi(st.substr(6,2).c_str());
int rd = atoi(ed.substr(6, 2).c_str());
int lH = atoi(st.substr(8, 2).c_str());
int rH = atoi(ed.substr(8, 2).c_str());
int lM = atoi(st.substr(10, 2).c_str());
int rM = atoi(ed.substr(10, 2).c_str());
node l = {0,ly, lm, ld, lH, lM, ""};
node r = {0,ry, rm, rd, rH, rM, ""};
node cur = {0, year, month, day, hour, minute, ""};
if (cur < l) {return -1;}
if (!(cur < r)) {return 1;}
return 0;
}
bool find(vector<int>& v, int x) {
for (auto& s : v) {
if (s == x) return true;
}
return false;
}
//TODO 特定年份,从一月份开始逐天进行比较,对每一天,判断是否有对应的任务,如果在给定时间范围内,就加到任务里
void solve() { // 特定年份
int month = 1; //
int week = getWeekOfDate(year, 1, 1); // 1月1日是周几
for (; month <= 12; month++) { //枚举月份
int day = 1;
int days = daysOfMonth[month]; // 阴历
if (month == 2) {
if (islunar(year)) days = 29;
else days = 28;
}
for (; day <= days; day++) {
int id = 0; //
for (auto& tas : tasks) {
if (tas.dayOfWeek.count(10086) || tas.dayOfWeek.count(week)) {
if (tas.month.count(10086) || tas.month.count(month)) {
if (tas.dayOfMonth.count(10086) || tas.dayOfMonth.count(day)) {
for (auto& mins : tas.minutes) {
for (auto& hous : tas.hours) {
if (mins == 10086) {
if (hous == 10086) {
for (int mm = 0; mm < 60; mm++) {
for (int hh = 0; hh < 24; hh++) {
node n_node = {id,year, month, day, hh, mm, tas.command};
if (between(year, month, day, hh, mm) == 0)
nodes.emplace_back(n_node);
}
}
} else {
for (int mm = 0; mm < 60; mm++) {
node n_node = {id,year, month, day, hous, mm, tas.command};
if (between(year, month, day, hous, mm) == 0)
nodes.emplace_back(n_node);
}
}
} else {
if (hous == 10086) {
for (int hh = 0; hh < 24; hh++) {
node n_node = {id,year, month, day, hh, mins, tas.command};
if (between(year, month, day, hh, mins) == 0)
nodes.emplace_back(n_node);
}
} else {
node n_node = {id,year, month, day, hous, mins, tas.command};
if (between(year, month, day, hous, mins) == 0)
nodes.emplace_back(n_node);
}
}
}
}
}
}
}
id++;
}
week = (week + 1) % 7;
}
}
}
void out(int x) {
if (x < 10) cout << 0 << x;
else cout << x;
}
int main() {
//cout << getWeekOfDate(2017,11,17);
//cout << getWeekOfDate(2017,11,17);
cin >> n >> st >> ed;
for (int i = 0; i < n; i++) {
readTask();
}
int ly = atoi(st.substr(0, 4).c_str());
int ry = atoi(ed.substr(0, 4).c_str());
for (year = ly; year <= ry; year++) {
solve();
}
set<node> st(nodes.begin(), nodes.end());
for (auto& str: st) {
out(str.year);
out(str.month);
out(str.day);
out(str.hour);
out(str.minute);
cout << ' ' << str.command << '\n';
}
};
/*
3 201711170032 201711222352
0 7 * * 1,3-5 get_up
30 23 * * Sat,Sun go_to_bed
15 12,18 * * * have_dinner
*/