Day of the Programmer
By: Richard Russell
Tags: Coding, Code, Python, Programming, Challenge

Not necessarily today

Problem

A time traveler invented a Time Machine and wants to test it by time-traveling to Russia on the Day of the Programmer (the 265th day of the year) during a year in the inclusive range from 1700 to 2700.

However, Russia had two different calendar systems. From 1700 to 1917, Russia’s official calendar was the Julian calendar, while they used the Gregorian calendar in 1919. During the transition year in 1918, the day after January 31st was February 14th. This meant that in 1918, February 14th was the 32nd day of the year in Russia.

In both calendar systems, February is the only month with a variable amount of days; it has 29 days during a leap year, and 28 days during all other years. In the Julian calendar, leap years are divisible by 4; in the Gregorian calendar, leap years are either of the following: divisible by 400, or divisible by 4 and not divisible by 100.

Given the year, y , find the date of the 256th day of that year according to the official Russian calendar during that year. Then, print it in the format dd.mm.yyyy where dd is the two-digit day, mm is the two-digit month, yyyy is y (the given year).

Brainstorm

Before approaching the problem, I had to pick off several key-points. These key points are as follows:

Finding the 256th day of the year

Constraint: 1700 ≤ y ≤ 2700

≤ 2700 In the years 1700–1917, Russia adopted the Julian calendar

1918 is a transitional year, where February 14th follows January 31st

1918-present, Russia adopted the Gregorian calendar.

From those key-points, I knew that the first step I had to do was figure out whether the input year is part of the Julian calendar, transitional year, or the Gregorian calendar. To tackle this problem, I created a simple if-else branch as follows:

def dayOfProgrammer(year):

if year <= 1917:

#Julian calendar

elif year == 1918:

#Transitional year

else:

#Gregorian calendar

Afterward, I need to figure out the different rules in applying leap-years. According to the problem, the rules of leap-years is as follows:

Julian calendar: divisible by 4

Transitional year: not a leap year

Gregorian calendar: either divisible by 400 or divisible by 4 and not divisible by 100

Following the rules above easily allow me to reconfigure the code and add the appropriate conditions:

def dayOfProgrammer(year):

if year <= 1917:

#Julian calendar

if year%4 == 0:

#Julian leap year

else:

#Julian not leap year

elif year == 1918:

#Transitional year (no leap year)

else:

#Gregorian calendar

if (year%4 == 0 and year%100 != 0) or year&400 == 0:

#Gregorian leap year

else:

#Gregorian not leap year

What’s interesting is the long conditional for the Gregorian leap year; seeing it gives a small burst of bliss (the illusion of complexity)

Solution

After brainstorming the solution and creating a structured outline of the code, I need to find the correct solution in order to solve this problem.

One important detail regarding this problem is that I do not need to calculate through each and every year to find the date of the 256th day. This is because of the fact that the 256th day is static in the years within the same category. For instance, the 256th day in the year 2020 and 2016 (both leap years using the Gregorian calendar) will be the same; 2001 and 2003 (both non-leap years using the Gregorian calendar) will also have the same date for the 256th day. However, the 256th day between the years 2020 and 2001 will obviously be different due to the additional date in February.

And so, I can calculate the 256th day by subtracting 256 to the cumulative number of days from January to August (as including September would be more than 256 days). Using simple addition and subtraction, I can find the date of both leap years and non-leap years:

Date for non-leap year: 256-(31+28+31+30+31+30+31+31) = 256-243 = 13

Meaning that the 256th day in non-leap years falls at 13 of the 9th month, or 13.09.yyyy

Date for leap year: 256-(31+29+31+30+31+30+31+31) = 256-244 = 12

Meaning that the 256th day in leap years fall at 12 of the 9th month, or 12.09.yyyy

Because both Julian and Gregorian calendar have the same rules regarding leap years — an additional day in February — then we can apply these rules for both calendar system.

Lastly, I can repeat the same process to find the 256th day during the transitional year by inputting 15 days for February.

Date for Transitional year: 256-(31+15+31+30+31+30+31+31) = 256-230 = 26

This means that during the Transitional year, the 256th day falls at exactly the 26 of the 9th month, or 26.09.1918

With these solutions in mind, I can finally add the final touches of my code and finish the problem:

def dayOfProgrammer(year):

if year <= 1917:

#Julian calendar

if year%4 == 0:

#Julian leap year

return "12.09." + str(year)

else:

#Julian not leap year

return "13.09." + str(year)

elif year == 1918:

#Transitional year (no leap year)

return "26.09.1918"

else:

#Gregorian calendar

if (year%4 == 0 and year%100 != 0) or year&400 == 0:

#Gregorian leap year

return "12.09." + str(year)

else:

#Gregorian not leap year

return "13.09." + str(year)

Of course, let us not forget the precious str() function, since strings cannot be concatenated.

Alternative Solutions

Self-reminder: one part of learning is to compare one’s work with other bright programmers. This is why I should visit the Discussions and Editorial boards more often.

Editorial Alternative

The code I wrote resembles most parts of the code published in the editorial. For one, the publisher also thought of dividing the years into three different parts: Julian calendar, transitional year, and Gregorian calendar. However, one major difference lies in how the publisher returned the output.

In my code, I manually calculated the date of the 256th day outside of the editor — meaning that I did it by hand. On a large scale perspective, it would be inefficient to manually work through a problem, especially if its size is bigger than what I could comprehend. What’s interesting is that the publisher calculated the date inside of the editor. His code is as follows:

int day = 256 - 31 - daysInFebruary - 31 - 30 - 31 - 30 - 31 -31;

assert(1 <= day && day <= 30);

printf("%02d.%02d.%04d", day, 9, y);

return 0;

Aside from the year acting as an external variable in the return function, the date of the 256th day also acted as an external variable which is calculated in the integer variable day . This is a good method if there are more additional rules added to the leap year rule (for example, the Roman calendar, which has 3 different rules to add to February).

Discussion Alternative

The post with most upvotes has a really creative solution:

def solve(year):

if (year == 1918):

return '26.09.1918'

elif ((year <= 1917) & (year%4 == 0) or ((year > 1918) & (year%400 = 0 or ((year%4 == 0) & (year%100 != 0)))):

return '12.09.%s' %year

else:

return '13.09.%s' %year

What he did was instead of categorizing the year by the calendar system, he branches the if statements based on the output. He knew that both Julian calendar and Gregorian calendar would have the 256th day on the 12 of the 9th month during the leap year, so he set his conditions to see whether the year falls for any of those calendar systems (leading to a more complex if condition that mine).

Another interesting method I noticed is how his first condition was to see whether the year was 1918, instead of figuring out whether the year was a non-leap year. This creates an effective and efficient code writing experience; instead of writing another long if condition, he only needed to figure out whether the year is equal to 1918. Finally, he concluded the statement with a simple else code.

Takeaways

I really enjoy doing this problem. It’s a logical and systematic problem that does not require knowledge of algorithms. A few key takeaways: