Code:
#include <stdio.h>
#include <assert.h>
#include <math.h>
#define INVALID_DATE (-1)
int leap_y(int y)
{
int k;
k = 0;
if(y % 4 == 0) k = 1;
if(y % 100 == 0) k = 0;
if(y % 400 == 0) k = 1;
if(y % 4000 == 0) k = 0;
return k;
}
int max(int y, int m)
{
int max, k;
k = leap_y(y);
if(m < 8)
{
if( (m == 2) && (k == 0) ) max = 28;
else if( (m == 2) && (k == 1)) max = 29;
else if ( (m % 2) == 0) max = 30;
else max = 31;
}
if(m >= 8)
{
if ( (m % 2) == 0) max = 31;
else max = 30;
}
return max;
}
int ConvertM(int y, int m)
{
int mm, k, d;
d = 0;
mm = 1;
k = leap_y(y);
if(m <= 8)
{
mm = m - 1;
while(mm != 0)
{
if( (mm == 2) && (k == 0) ) {d = d + 28;}
else if( (mm == 2) && (k == 1)) {d = d + 29;}
else if ( (mm % 2) == 0) {d = d + 30;}
else {d = d + 31;}
mm--;
}
}
if(m > 8){
mm = m - 1;
while(mm >= 8)
{
if ( (mm % 2) == 0) d = d + 31;
else d = d + 30;
mm--;
}
if(k == 1) d = d + 213;
if(k == 0) d = d + 212;
}
return d;
}
int Convert(int y, int m, int d)
{
int value, leap, leap1, l, l1, k;
k = leap_y(y);
y = y - 2000;
m = ConvertM(y, m);
leap1 = 366;
leap = 365;
l = 0;
l1 = 0;
while (y != 0)
{
k = leap_y(y);
if( k == 1)
{
l1++;
}
if( k == 0)
{
l++;
}
y--;
}
value = l1*leap1 + l*leap + m + d;
return value;
}
int isFullMoon ( int y, int m, int d )
{
int k, fullmoon, vali, mx;
double val, diff, cons1, cons2, val1;
cons1 = 29.53059027;
cons2 = 197.58;
fullmoon = 1;
k = leap_y(y);
mx = max(y, m);
if(y < 2000) return INVALID_DATE;
if(m < 1 || m >12) return INVALID_DATE;
if(d < 1 || d > mx) return INVALID_DATE;
val = Convert(y, m, d);
val1 = (val - cons2)/cons1;
vali = val1;
diff = fabs(val1 - vali);
if(k == 0)
{
if(diff > 0.962 && diff <= 1)
{
fullmoon = 1;
}
else fullmoon = 0;
}
if(k == 1)
{
if(diff >= 0 && diff < 0.0485)
{
fullmoon = 1;
}
else fullmoon = 0;
}
return fullmoon;
}
int prevFullMoon ( int y, int m, int d,
int * prevY, int * prevM, int * prevD )
{
int i, mx;
mx = max(y, m);
if(y < 2000) return INVALID_DATE;
if(m < 1 || m >12) return INVALID_DATE;
if(d < 1 || d > mx) return INVALID_DATE;
i = isFullMoon(y, m, d);
if(i == 1)
{
d = d - 1;
do
{
d--;
if(d == 0)
{
if(m == 1)
{
y = y - 1;
m = 12;
}
else m = m - 1;
mx = max(y, m);
d = mx;
}
i = isFullMoon(y, m, d);
}while(i != 1);
}
if(i == 0)
{
do
{
d--;
if(d == 0)
{
if(m == 1)
{
y = y - 1;
m = 12;
}
else m = m - 1;
mx = max(y, m);
d = mx;
}
i = isFullMoon(y, m, d);
}while(i != 1);
}
*prevY = y;
*prevM = m;
*prevD = d;
return 1;
}
int nextFullMoon ( int y, int m, int d,
int * nextY, int * nextM, int * nextD )
{
int i, mx;
mx = max(y, m);
if(y < 2000) return INVALID_DATE;
if(m < 1 || m >12) return INVALID_DATE;
if(d < 1 || d > mx) return INVALID_DATE;
i = isFullMoon(y, m, d);
mx = max(y, m);
if(i == 1)
{
d = d + 1;
do
{
d++;
if(d == mx)
{
if(m == 12)
{
y = y + 1;
m = 1;
}
else m = m + 1;
d = 1;
}
i = isFullMoon(y, m, d);
}while(i != 1);
}
if(i == 0)
{
do
{
d++;
if(d == mx)
{
if(m == 12)
{
y = y + 1;
m = 1;
}
else m = m + 1;
d = 1;
}
i = isFullMoon(y, m, d);
}while(i != 1);
}
*nextY = y;
*nextM = m;
*nextD = d;
return 1;
}
int main ( int argc, char * argv [] )
{
int y, m, d;
assert ( isFullMoon ( 2017, 1, 11 ) == 0 );
assert ( isFullMoon ( 2017, 1, 12 ) == 1 );
assert ( isFullMoon ( 2017, 1, 13 ) == 0 );
assert ( isFullMoon ( 2017, 11, 3 ) == 0 );
assert ( isFullMoon ( 2017, 11, 4 ) == 1 );
assert ( isFullMoon ( 2017, 11, 5 ) == 0 );
assert ( isFullMoon ( 2019, 12, 11 ) == 1 );
assert ( isFullMoon ( 2019, 12, 12 ) == 0 );
assert ( isFullMoon ( 2019, 12, 13 ) == 0 );
assert ( isFullMoon ( 2000, 7, 16 ) == 1 );
assert ( isFullMoon ( 2016, 12, 14 ) == 1);
assert ( prevFullMoon ( 2017, 1, 11, &y, &m, &d ) == 1 && y == 2016 && m == 12 && d == 14 );
assert ( prevFullMoon ( 2017, 1, 12, &y, &m, &d ) == 1 && y == 2016 && m == 12 && d == 14 );
assert ( prevFullMoon ( 2017, 1, 13, &y, &m, &d ) == 1 && y == 2017 && m == 1 && d == 12 );
assert ( prevFullMoon ( 2017, 11, 3, &y, &m, &d ) == 1 && y == 2017 && m == 10 && d == 5 );
assert ( prevFullMoon ( 2017, 11, 4, &y, &m, &d ) == 1 && y == 2017 && m == 10 && d == 5 );
assert ( prevFullMoon ( 2017, 11, 5, &y, &m, &d ) == 1 && y == 2017 && m == 11 && d == 4 );
assert ( prevFullMoon ( 2019, 12, 11, &y, &m, &d ) == 1 && y == 2019 && m == 11 && d == 12 );
assert ( prevFullMoon ( 2019, 12, 12, &y, &m, &d ) == 1 && y == 2019 && m == 12 && d == 11 );
assert ( prevFullMoon ( 2019, 12, 13, &y, &m, &d ) == 1 && y == 2019 && m == 12 && d == 11 );
assert ( nextFullMoon ( 2017, 1, 11, &y, &m, &d ) == 1 && y == 2017 && m == 1 && d == 12 );
assert ( nextFullMoon ( 2017, 1, 12, &y, &m, &d ) == 1 && y == 2017 && m == 2 && d == 11 );
assert ( nextFullMoon ( 2017, 1, 13, &y, &m, &d ) == 1 && y == 2017 && m == 2 && d == 11 );
assert ( nextFullMoon ( 2017, 11, 3, &y, &m, &d ) == 1 && y == 2017 && m == 11 && d == 4 );
assert ( nextFullMoon ( 2017, 11, 4, &y, &m, &d ) == 1 && y == 2017 && m == 12 && d == 3 );
assert ( nextFullMoon ( 2017, 11, 5, &y, &m, &d ) == 1 && y == 2017 && m == 12 && d == 3 );
assert ( nextFullMoon ( 2019, 12, 11, &y, &m, &d ) == 1 && y == 2020 && m == 1 && d == 10 );
assert ( nextFullMoon ( 2019, 12, 12, &y, &m, &d ) == 1 && y == 2020 && m == 1 && d == 10 );
assert ( nextFullMoon ( 2019, 12, 13, &y, &m, &d ) == 1 && y == 2020 && m == 1 && d == 10 );
assert ( prevFullMoon ( 2000, 7, 16, &y, &m, &d ) == 1 && y == 2000 && m == 6 && d == 17);
assert ( isFullMoon ( 2017, 1, 12 ) == 1 );
assert ( isFullMoon ( 2017, 2, 11 ) == 1 );
assert ( isFullMoon ( 2017, 3, 12 ) == 1 );
assert ( isFullMoon ( 2017, 4, 11 ) == 1 );
assert ( isFullMoon ( 2017, 5, 10 ) == 1 );
assert ( isFullMoon ( 2017, 6, 9 ) == 1 );
assert ( isFullMoon ( 2017, 7, 9 ) == 1 );
assert ( isFullMoon ( 2017, 8, 7 ) == 1 );
assert ( isFullMoon ( 2017, 9, 6 ) == 1 );
assert ( isFullMoon ( 2017, 10, 5 ) == 1 );
assert ( isFullMoon ( 2017, 11, 4 ) == 1 );
assert ( isFullMoon ( 2017, 12, 3 ) == 1 );
assert ( isFullMoon ( 2018, 1, 2 ) == 1 );
assert ( isFullMoon ( 2018, 1, 31 ) == 1 );
assert ( isFullMoon ( 2018, 3, 2 ) == 1 );
assert ( isFullMoon ( 2018, 3, 31 ) == 1 );
assert ( isFullMoon ( 2018, 4, 30 ) == 1 );
assert ( isFullMoon ( 2018, 5, 29 ) == 1 );
assert ( isFullMoon ( 2018, 6, 28 ) == 1 );
assert ( isFullMoon ( 2018, 7, 27 ) == 1 );
assert ( isFullMoon ( 2018, 8, 26 ) == 1 );
assert ( isFullMoon ( 2018, 9, 25 ) == 0 );
assert ( isFullMoon ( 2018, 10, 24 ) == 1 );
assert ( isFullMoon ( 2018, 11, 23 ) == 1 );
assert ( isFullMoon ( 2018, 12, 22 ) == 1 );
assert ( isFullMoon ( 2019, 1, 21 ) == 1 );
assert ( isFullMoon ( 2019, 2, 19 ) == 1 );
assert ( isFullMoon ( 2019, 3, 21 ) == 1 );
assert ( isFullMoon ( 2019, 4, 19 ) == 1 );
assert ( isFullMoon ( 2019, 5, 18 ) == 0 );
assert ( isFullMoon ( 2019, 6, 17 ) == 1 );
assert ( isFullMoon ( 2019, 7, 16 ) == 0 );
assert ( isFullMoon ( 2019, 8, 15 ) == 1 );
assert ( isFullMoon ( 2019, 9, 14 ) == 1 );
assert ( isFullMoon ( 2019, 10, 13 ) == 1 );
assert ( isFullMoon ( 2019, 11, 12 ) == 1 );
assert ( isFullMoon ( 2019, 12, 12 ) == 0 );
assert ( prevFullMoon ( 2000, 11, 31, &y, &m, &d ) == INVALID_DATE );
assert ( nextFullMoon ( 2001, 2, 29, &y, &m, &d ) == INVALID_DATE );
assert ( isFullMoon ( 2004, 2, 29 ) == 0 );
assert ( prevFullMoon ( 2048, 2, 26, &y, &m, &d ) == 1 && y == 2048 && m == 1 && d == 30);
assert ( prevFullMoon ( 2100, 2, 29, &y, &m, &d ) == INVALID_DATE );
assert ( nextFullMoon ( 2000, 2, 29, &y, &m, &d ) == 1 && y == 2000 && m == 3 && d == 20 );
return 0;
}