CSP 201712-3 Crontab

写的很长啊,基本思路是枚举每一年的每一天,然后枚举每一个任务,判断是否符合,一个字符串划分的小技巧是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
 */

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值