Wikitext, #time parser function: Find last month with five Mondays

26 Views Asked by At

in Asphalt Wiki, we have templates for repeating events in the Asphalt games. These templates also display if an event is currently running.

In one of the games, events are bound to days of the month and their position within the month, for example, an event is only held on the third Wednesday of a month. Each event has four versions except one whose versions are held on the first, second, ..., fifth Monday of a month.

We also have a template {{event status}} that calculates the status of an event, given the last start date and the duration: https://asphalt.fandom.com/wiki/Template:Event_status

To calculate the status of the event held on the fifth Monday of a month, it is therefore necessary to find the last month that has five Mondays.

What I have so far: Let days be the number of days of a month, then you only have to check if the first days - 28 days of this month are a Monday. In common years, days - 28 is 0, 2 or 3, in leap years, it's 1, 2 or 3. This can easily be checked with or.

My problem is: How many months must I go back to be sure to get a month with five Mondays? We don't have something like a do while loop, so I'd have to calculate it.

I tested it for a few years and found that there never seem to be more than 3 months with only four Mondays, so going back 4 months should be enough. But this seems to be a bit uncertain—unless someone can show me a proof that there can be at most 3 months without a fifth Monday between months with five Mondays.

Any ideas how to calculate and not guess this?

Thanks in advance!

Edit: Found the proof that there can never be more than 3 months without a Monday in the "extra" days.

  1. The days - 28 extra days of a month always have the same name as the days - 28first days of the month (because 28 is four full weeks).

  2. The first days of the following month continue the sequence of the last days of the previous month as the sequence of weekdays is never interrupted.

  3. Therefore the extra days are an uninterrupted repeating sequence of the 7 weekdays as well.

We just have to search for the longest sequence of months where the sum of extra days is less than 9 because on the 8th day, the wanted weekday will repeat.

  1. In our calendar, every month with less than 31 days is surrounded by two months with 31 days, so we can be sure two have 2 times 3 extra days in any sequence of 3 days we pick.

  2. The sequence with the smallest sum is always one that includes the February of a common year as this is the only month with just 28 days and 0 extra days.

  3. The smallest sum of extra days is in the sequence starting with Jan (3), then Feb (0) and Mar (3). The next month (Apr) will always have 2 extra days, so the sum is 8.

  4. If the first day of this sequence is a Monday, it will repeat on the 8th day and thus lie within the sequence of four months.

  5. If the Monday is on the second or third day of the sequence, we need one additional month (May with 3 extra days), but we can be sure that the Monday then appears in May.

So it's true that there are never more than 3 consecutive months without a Monday in their extra days.

Basically, we have to find the longest subsequence in the sequence below where the sum of its numbers is less than 10. I increased the limit to 10 because the Monday can be on the third day of the first month in the sequence.

... 2 3 2 3 | 3 0 3 2 3 2 3 3 2 3 2 3 | 3 0 3 2 3 ...

Although I now know that 4 "if contains Monday" checks are enough, I'd still be interested in a way to calculate the months I have to go back instead of brute force checking 4 times.