/* 2020/2021 North America Championship International Collegiate Programming Contest Problem ? Daily Cron M. K. Furon. 2021-03-31. */ #include #include #include #include #include int croncount, hh, i, iocount, job, jobcount, jobtrigger, mm, ss; int timecount; unsigned int hourbit, hourmatch; unsigned long long int minutebit, minutematch, secondbit, secondmatch; char *token; char lineimage[1024]; struct cronspec { unsigned int hourmap; unsigned long long int minutemap; unsigned long long int secondmap; } cronentry[100]; void abend (char *message) { (void) fputs (message, stderr); (void) fputc ('\n', stderr); exit (4); } unsigned long long int valuemap (char *valuelist, int maxvalue) { unsigned int bitcount, number1, number2; unsigned long long int bitsset, result; char *nextvalue; /* Turn a list of values into a bit map for those values. The maximum value constrains the size of the bit map. Asterisk means "all values". */ if (*valuelist == '*') /* If all values "wild card" */ result = (1LL << (maxvalue + 1)) - 1LL; else { result = 0; while (*valuelist) { number1 = (int) strtoul (valuelist, &nextvalue, 10); if ((*nextvalue == ((char) 0)) || (*nextvalue == ',')) { /* Number is a single value. */ result |= (1LL << number1); if (*nextvalue == ',') nextvalue++; valuelist = nextvalue; } else if (*nextvalue == '-') /* If range is specified */ { nextvalue++; number2 = (int) strtoul (nextvalue, &nextvalue, 10); if (number2 <= number1) abend ("Incorrect range specified."); /* Set the bits corresponding to the values in the range. */ bitcount = number2 - number1 + 1; bitsset = (1LL << bitcount) - 1LL; result |= bitsset << number1; if (*nextvalue == ',') nextvalue++; valuelist = nextvalue; } } } return (result); } int main (int argc, char *argv[], char *envp[]) { /* Ingest the "crontab" time specifications, one per line. */ (void) fgets (lineimage, 1020, stdin); iocount = sscanf (lineimage, "%d", &croncount); if (iocount != 1) abend ("Incorrect cron line count."); for (i = 0; i < croncount; i++) { (void) fgets (lineimage, 1020, stdin); /* Strip the trailing new-line from the input buffer. */ lineimage[((strlen (lineimage)) - 1)] = (char) 0; token = strtok (lineimage, " \t"); cronentry[i].hourmap = (int) valuemap (token, 23); token = strtok (NULL, " \t"); cronentry[i].minutemap = valuemap (token, 59); token = strtok (NULL, " \t"); cronentry[i].secondmap = valuemap (token, 59); } /* Process the entries for each second of the day. If at least one entry is triggered in a given second, increment the time counter. Increment the job counter for each job triggered. */ jobcount = timecount = 0; for (hh = 0; hh < 24; hh++) { hourbit = 1 << hh; for (mm = 0; mm < 60; mm++) { minutebit = 1LL << mm; for (ss = 0; ss < 60; ss++) { secondbit = 1LL << ss; jobtrigger = 0; for (job = 0; job < croncount; job++) { hourmatch = hourbit & cronentry[job].hourmap; minutematch = minutebit & cronentry[job].minutemap; secondmatch = secondbit & cronentry[job].secondmap; if (hourmatch && minutematch && secondmatch) jobtrigger++; } if (jobtrigger) { timecount++; jobcount += jobtrigger; } } } } (void) printf ("%d %d\n", timecount, jobcount); return (0); }