1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdbool.h>
- #include <ctype.h>
- #include <math.h>
- #include <errno.h>
- #include <limits.h>
- #define METONIC_PERIOD 19
- void usage() {
- fprintf(stderr, "Usage: easter <YYYY>\n");
- }
- bool is_year(char *arg) {
- int c = *arg == '-' ? 1 : 0; // Skip leading negative sign
- while(*(arg + c) != '\0') {
- if(!isdigit(*(arg + c))) {
- return false;
- }
- ++c;
- }
- return true;
- }
- bool strtoy(char *y_str, long *y_num) {
- errno = 0;
- *y_num = strtol(y_str, NULL, 10);
- if((errno == ERANGE && (*y_num == LONG_MAX || *y_num == LONG_MIN))
- || (errno != 0 && *y_num == 0)) {
- return false;
- }
- return true;
- }
- // Ref: https://en.wikipedia.org/wiki/Computus#Algorithms
- void easter(const long year) {
- long a = year % METONIC_PERIOD;
- long b = year/100;
- long c = year%100;
- long d = b/4;
- long e = b%4;
- long f = (b + 8)/25;
- long g = (b - f + 1)/3;
- long h = (19*a + b - d - g + 15) % 30;
- long i = c/4;
- long k = c%4;
- long l = (32 + 2*e + 2*i - h - k) % 7;
- long m = (a + 11*h + 22*l)/451;
- long date = h + l - 7*m + 114;
- long month = date/31;
- long day = date % 31 + 1;
-
- printf("%04ld-%02ld-%02ld\n", year, month, day);
- }
- int main(int argc, char **argv) {
- if(argc != 2) {
- usage();
- exit(1);
- }
- if(!is_year(argv[1])) {
- usage();
- exit(1);
- }
- long Y;
- if(!strtoy(argv[1], &Y)) {
- usage();
- exit(1);
- }
-
- easter(Y);
- return 0;
- }
|