## Five Weekends

### October 16, 2018

This task comes to us from Rosetta Code: The month of October 2010 has five Fridays, five Saturdays and five Sundays.

Your task is to count and make a list of all months from 1900 to 2100, inclusive, that have five Fridays, Saturdays and Sundays, and to count and make a list of all years from 1900 to 2100, inclusive, that have no such months. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

### 3 Responses to “Five Weekends”

1. Alex B said

I saw this as one of those viral posts on Facebook a few years ago, claiming that this happened only once in a few hundred years, and was ‘lucky’ according to ancient Chinese custom.
At that point I debunked it using Excel, but here’s a quick Python version. It operates on the principle that only 31 day months which start on Friday have this characteristic.

```from calendar import weekday, FRIDAY
from collections import defaultdict
POSSIBLE_MONTHS = [1, 3, 5, 7, 8, 10, 12]

def five_weekends(year, month):
return weekday(year, month, 1) == FRIDAY

results = defaultdict(list)
number = 0
has_no_five_weekend_months = []
for year in range(1900, 2101):
for month in POSSIBLE_MONTHS:
if five_weekends(year, month):
results[year].append(month)
number += 1
if results[year] == []:
has_no_five_weekend_months.append(year)

print(f'{len(has_no_five_weekend_months)} years have no five-weekend months:')
for year in has_no_five_weekend_months:
print(f'\t{year}')

print('Months with five weekends:')
for year in results:
if results[year] != []:
print(f'\t{year}\t{results[year]}')
```

Results:

```29 years have no five-weekend months:
1900
1906
1917
1923
1928
.
.
.
2085
2091
2096
Months with five weekends:
1901	[3]
1902	[8]
1903	[5]
1904	[1, 7]
.
.
.
2094	[1, 10]
2095	[7]
2097	[3]
2098	[8]
2099	[5]
2100	[1, 10]
```
2. kernelbob said

/bin/sh is the language of choice. Find months for which /usr/bin/cal prints 31 on a line by itself.

```#!/bin/sh

y=1900
count=0
while [ \$y -le 2100 ]
do
f=0
for m in 1 3 5 7 8 10 12
do
if LANG=C cal \$m \$y | grep -q '^31'
then
echo \$y \$m
f=1
count="`expr \$count + 1`"
fi
done
[ \$f -eq 0 ] && echo \$y none
y="`expr \$y + 1`"
done
echo \$count 5-weekend months
```
3. Daniel said

Here’s a solution in C.

```#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[]) {
int y_start = 1900;
int n_years = 201;
static int candidates[] = {1, 3, 5, 7, 8, 10, 12};
static int n_candidates = sizeof(candidates) / sizeof(int);
uint8_t year_months[n_years];
for (int i = 0; i < n_years; ++i) {
uint8_t months = 0;
for (int j = 0; j < n_candidates; ++j) {
int y = y_start + i;
int m = candidates[j];
int d = 1;
int dow = (d+=m<3?y--:y-2,23*m/9+d+4+y/4-y/100+y/400)%7;
if (dow == 5) months |= (1 << j);
}
year_months[i] = months;
}
int counter = 0;
printf("*** Five Weekend Months ***\n\n");
for (int i = 0; i < n_years; ++i) {
int y = y_start + i;
uint8_t months = year_months[i];
if (!months) continue;
for (int j = 0; j < n_candidates; ++j) {
if (1 & months) {
++counter;
printf("%d. %02d/%d\n", ++counter, candidates[j], y);
}
months >>= 1;
}
}
counter = 0;
printf("\n*** Years Missing Five Weekend Months ***\n\n");
for (int i = 0; i < n_years; ++i) {
int y = y_start + i;
if (!year_months[i]) {
++counter;
printf("%d. %d\n", counter, y);
}
}
return EXIT_SUCCESS;
}
```

Output:

```*** Five Weekend Months ***

1. 03/1901
2. 08/1902
3. 05/1903
4. 01/1904
5. 07/1904
6. 12/1905
7. 03/1907
...
195. 10/2094
196. 07/2095
197. 03/2097
198. 08/2098
199. 05/2099
200. 01/2100
201. 10/2100

*** Years Missing Five Weekend Months ***

1. 1900
2. 1906
3. 1917
4. 1923
5. 1928
6. 1934
7. 1945
...
23. 2057
24. 2063
25. 2068
26. 2074
27. 2085
28. 2091
29. 2096
```