## Thank God It’s Friday!

### June 24, 2011

The function for Gauss’ method is shown below. We changed the decimals to fractions so that all the calculations would be done in exact arithmetic.

```(define (day-of-week year month day) ; gauss method   (let* ((yr (if (< month 3) (- year 1) year))          (m (if (< month 3) (+ month 10) (- month 2)))          (y (modulo yr 100)) (c (quotient yr 100)))     (list-ref '(sun mon tue wed thu fri sat)       (modulo (+ day (floor (- (* 13/5 m) 1/5)) y                  (quotient y 4) (quotient c 4) (- (* 2 c))) 7))))```

```> (day-of-week 2011 6 24) fri```

Here is our version of Sakamoto’s method:

```(define (day-of-week year month day) ; sakamoto method   (let ((t (vector 0 3 2 5 0 3 5 1 4 6 2 4))         (y (if (< month 3) (- year 1) year)))     (list-ref '(sun mon tue wed thu fri sat)       (modulo (+ day y (quotient y 4) (- (quotient y 100))               (quotient y 400) (vector-ref t (- month 1))) 7))))```

```> (day-of-week 2011 6 24) fri```

Conway’s method is more of a challenge. Here is the calculation of the anchor day:

```(define (anchor year)   (let ((c (+ (quotient year 100) 1)))     (list-ref '(sun mon tue wed thu fri sat)       (modulo (+ (* 5 c) (quotient (- c 1) 4) 4) 7))))```

```> (anchor 2011) tue```

Given an anchor day, here is the function to calculate the doomsday:

```(define (doomsday year)   (let* ((days '(sun mon tue wed thu fri sat))          (y (modulo year 100))          (q (quotient y 12))          (r (remainder y 12))          (x (quotient r 4))          (c (+ (quotient year 100) 1))          (anchor (+ (* 5 c) (quotient (- c 1) 4) 4)))     (list-ref days (modulo (+ q r x anchor) 7))))```

```> (doomsday 2011) mon```

It is easier for a computer, though perhaps not for a mentalist, to calculate the doomsday like this:

```(define (doomsday year)   (list-ref '(sun mon tue wed thu fri sat)     (modulo (+ 2 year (quotient year 4)       (- (quotient year 100)) (quotient year 400)) 7)))```

```> (doomsday 2011) mon```

You can run the program at http://programmingpraxis.codepad.org/BeTpy03N, which also includes the code for the method from the Standard Prelude and Zeller’s congruence for comparison. Note that Zeller’s congruence is essentially the same as Gauss’ method.

Pages: 1 2

### 5 Responses to “Thank God It’s Friday!”

1. […] today’s Programming Praxis exercise, our goal is to implement three functions related to dates: two ways to […]

```data Weekday = Sun | Mon | Tue | Wed | Thu | Fri | Sat deriving (Enum, Eq, Show)

gauss :: Int -> Int -> Int -> Weekday
gauss y m d = toEnum \$ mod (d + floor (2.6 * fromIntegral
(mod (m - 2) 12) - 0.2) + y' + div y' 4 + div c 4 - 2*c) 7 where
(c,y') = divMod (if m < 3 then y - 1 else y) 100

sakamoto :: Int -> Int -> Int -> Weekday
sakamoto y m d = toEnum \$ mod (y + div y 4 - div y 100 +
div y 400 + [0,3,2,5,0,3,5,1,4,6,2,4] !! (m - 1) + d) 7

conway :: Int -> Weekday
conway y = toEnum \$ mod (q + r + div r 4 + 5*(c+1) + div c 4 + 4) 7
where (c, (q,r)) = (div y 100, divMod (mod y 100) 12)
```
3. Graham said

My Python submission (basically just a translation of the Scheme solution):

```#!/usr/bin/env python

from fractions import Fraction

DAYS = {0: "Sunday", 1: "Monday", 2: "Tuesday", 3: "Wednesday", 4: "Thursday",
5: "Friday", 6: "Saturday"}

def gauss(year, month, day):
yr = (year - 1) if (month < 3) else year
m = (month + 10) if (month < 3) else (month - 2)
c, y = divmod(yr, 100)
return DAYS[sum((day, int((Fraction('13/5') * m) - Fraction('1/5')), y,
(y / 4), (c / 4), - 2 * c)) % 7]

def sakamoto(year, month, day):
t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
y = (year - 1) if (month < 3) else year
return DAYS[sum((day, y, (y / 4), - (y / 100), (y / 400), t[month - 1]))
% 7]

def doomsday(year):
return DAYS[sum((2, year, year / 4, - (year / 100), year / 400)) % 7]

if __name__ == "__main__":
print gauss(2011, 6, 24)
print sakamoto(2011, 6, 24)
print doomsday(2011)
```
4. Mike said

Python version

Tried all the formulas from Wikipedia for conway’s method. And went all the way to calculate the day of the week.

```dow = "Sun Mon Tue Wed Thu Fri Sat".split()

def leap(year):
return bool(not year % 400 or not year % 4 and year % 100)

def gauss(year, month, day):
c, y = divmod(year if month > 2 else (year - 1), 100)
m = (month - 3)%12 + 1
return dow[(day + int(2.6*m - 0.2) + y + y//4 + c//4 - 2*c) % 7]

def sakamoto(year, month, day):
t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
y = year if month > 2 else (year - 1)
return dow[(day + y + y//4 - y//100 + y//400 + t[month - 1]) % 7]

def conway(year, month, day):
c, y = divmod(year, 100)

# original formula
#c += 1
#anchor = (5*c + (c-1)//4 + 4)%7
# modified formula-don't add 1 to first 2 digits of year.
anchor = (5*c + c//4 + 2)%7

# original conway formula
#doomsday = (anchor + y//12 + y%12 + y%12//4)%7

# alternative from wikipedia.  I think this is easiest to do in head.
doomsday = (anchor + y + y//4)%7

# odd+11 rule from wikipedia
#y = (y+11) if y&1 else y
#y = y//2
#y = (y+11) if y&1 else y
#y = 7 - y%7
#doomsday = (anchor + y)%7

#computer formula from wikipedia
#doomsday =  (2 + y + y//4 - y//100 + y//400)%7

nearest = (10, 28, 0, 4, 9, 6, 11, 8, 5, 10, 7, 12)[month - 1]
if month < 3 and leap(year):
nearest += 1

return dow[(doomsday + day - nearest) % 7]
```
5. razvan said

Here’s my solution in Java:

```package dayofweek;

public class DayOfWeek {

private static final int[] SAKAMOTO_TABLE = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6,
2, 4 };

private static void checkDate(int d, int m, int y) {
if (m < 1 || m > 12)
if (d < 0 || d > 31)
if (m == 2
&& (d > 29 || d > 28
&& ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)))
if (y < 0)
}

public static int gauss(int d, int m, int y) {
checkDate(d, m, y);
if (m >= 3 && m <= 12)
m -= 2;
else if (m < 3 && m > 0) {
m += 10;
y--;
}
int c = y / 100;
y %= 100;
return (d + (int) Math.floor(2.6 * (double) m - 0.2) + y + y / 4 + c
/ 4 - 2 * c) % 7;
}

public static int sakamoto(int d, int m, int y) {
checkDate(d, m, y);
if (m < 3 && m > 0)
y--;
return (y + y / 4 - y / 100 + y / 400 + SAKAMOTO_TABLE[m - 1] + d) % 7;
}

public static int conway(int d, int m, int y) {
checkDate(d, m, y);
int c = y / 100 + 1;
int anchor = ((5 * c + (c - 1) / 4) % 7 + 4) % 7;
int yy = y % 100;
int quo = yy / 12, rem = yy % 12;
int doomsday = ((quo + rem + rem / 4) % 7 + anchor) % 7;
int doom = 0;
if (m == 4 || m == 6 || m == 8 || m == 10 || m == 12)
doom = m;
else if (m == 2) {
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
doom = 29;
else
doom = 28;
} else if (m == 3)
doom = 0;
else if (m == 3) {
if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0)
doom = 11;
else
doom = 10;
} else
switch (m) {
case 5:
doom = 9;
break;
case 7:
doom = 11;
break;
case 9:
doom = 5;
break;
case 11:
doom = 7;
break;
}

if (d > doom)
return ((d - doom) % 7 + doomsday) % 7;
else
return ((doomsday - (doom - d) % 7) + 7) % 7;
}

public static String intToDate(int d) {
switch (d) {
case 0:
return "Sunday";
case 1:
return "Monday";
case 2:
return "Tuesday";
case 3:
return "Wednesday";
case 4:
return "Thursday";
case 5:
return "Friday";
case 6:
return "Saturday";
}
throw new NumberFormatException("Bad day of week");
}

public static void main(String[] args) {
System.out.println(intToDate(gauss(24, 6, 2011)));
System.out.println(intToDate(sakamoto(24, 6, 2011)));
System.out.println(intToDate(conway(11, 5, 2010)));
}

}
```