简体   繁体   中英

Quickest Algorithm For This Interesting Occurence

When using a Lunar Calendar a year consist of 52 Weeks in the US, according to this Seven Day Week Entry on WikiPeda .

Calculation Assumptions

  1. 12 Months x 4 Weeks = 48 Weeks
  2. 48 Weeks x 7 days = 336 Days
  3. We Now Make up 4 Weeks and 1 day to match the Lunar Calender to our year(365.25 - 336 = 29)
  4. 7 months have an extra 3 days (21)
  5. 4 months have 2 extra(8)
  6. We add 1 Day to February every 4 years to account for the quarter of a day. Commonly referred to as a Leap Year

Using these Calculation Assumptions, I want the general algorithm, regardless of language that tells me which months have repeating days of 5.
See this question .(This only gives me Fridays, and I don't know if the answer is optimized)

I want to add the following:
Why 5 Fridays, 5 Saturdays and 5 Sundays don't occur every 823 years ,

so that given any reasonable year only, the algorithm returns every combination of months within that year where the days repeat 5 times, so that I don't have to go to the link above to figure out what they are.


LANGUAGE DEPENDENT FUNCTIONS AND METHODS :

In the spirit of the great answer below, I thought I'd add some of the built-in functions Jim Mischel referred to:

Those are the major ones. If anyone has more, please let me know.

Note that just about any programming language these days comes with library functions that will do all this for you. Or there is such a library available from a third party. But if you want to calculate it yourself . . .

As your link explains, any month with 31 days will have five occurrences of three days. If the month starts on Sunday, then there will be five Sundays, five Mondays, and five Tuesdays.

If you know what day the first day of the year falls on, then it's easy to compute the first day of any month. If you number the days with 0 as Sunday, 1 is Monday, 2 is Tuesday, etc., then you can find the first day of any month by doing a little modulo arithmetic.

The first day of February is equal to the first day of January plus 31, mod 7. That is:

feb1 = (jan1 + 31) % 7

So 2014 started on a Wednesday. That would be day number 3.

(3 + 31) % 7 = 34 % 7 = 6 (Saturday)

Which you can verify by looking at a calendar for this year.

Calculating other months using that technique would require that you build a table that contains the cumulative number of days at the end of each month. But that's not necessary. All you really need is a table of 12 entries that tell you the offsets for each month, and a little logic to add 1 for months later than February in leap years.

Take 2014, for example. The table below shows what day each month starts on.

January   Wednesday (3)
February  Saturday (6)
March     Saturday (6)
April     Tuesday (2)
May       Thursday (4)
June      Sunday (0)
July      Tuesday (2)
August    Friday (5)
September Monday (1)
October   Wednesday (3)
November  Saturday (6)
December  Monday(1)

What we really need is offsets for each month. You see that the difference between the first day of February and the first day of January is 3. Same for March. For April, the difference is -1. For that to work in modulo arithmetic, you'll want to make that 6. Anyway, you can build a table that tells you the offset you need to add for each month:

January   0
February  3
March     3
April     6
May       1
June      4
July      6
August    2
September 5
October   0
November  3
December  5

Given that, if you know the first day of the year, then you can compute the first day of any month. Consulting a calendar, you see that the first day of September 2014 is Monday. Let's see if the formula works. The first day of January was a Wednesday, and the offset table says that we need to add an offset of 5 for September:

(3 + 5) % 7 = 1 (Monday)

For leap years, you need to add one to the offset if you're looking for a month after February. Take 2012. The first day of January was Sunday. Using the same formula as above, and adding 1 for the leap year, September 1, 2012 was:

(0 + 5 + 1) % 7 = 6 (Saturday)

The only trick is finding the day of the week for January 1, and you were given a link for that in a comment. After that it's a simple table lookup, an addition, and modulo arithmetic.

By the way, you could speed the algorithm slightly by creating a second offset table to be used for leap years. That table would be:

January   0
February  3
March     4
April     0
May       2
June      5
July      0
August    3
September 6
October   1
November  4
December  6

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM