views:

962

answers:

7

I'd like to be able to start with a year, and calculate occurrences of Friday the 13th. A brute force solution is easy and obvious. I have something slightly better, but I have no doubt that someone else can come up with an elegant algorithm for this.

Perhaps a little trickier, I'd be interested in giving the program a month, and have it find the next year in which that month has a Friday the 13th.

Feel free to use pseudo code, but I expect people will vote more for working code samples in you favorite language.

+1  A: 
initialize startDate to 13th of the month given in the current year
while (true) {
    if (startDate.dayOfWeek == Date.FRIDAY)
         break;
    else
         startDate.year ++;
}
return startDate.year;
Elie
+8  A: 

Since your brute force algorithm is apparently the intuitive day-by-day iteration option, perhaps you haven't considered the Doomsday Algorithm. It would allow you to simply check if that 13th is a Friday. As far as I know, it is the most efficient solution to the problem.

Devin Jeanpierre
+7  A: 

Any month that starts with a Sunday has a Friday on the thirteenth. There are only 14 combinations possible knowing what day the first of the year is on (with or without leap year, and sun-sat). You should just calculate it once and get it over with. You'd only check 14*12 possible months to start out with, well with in reason.

resultant table element (from 2009, 2010):

[Thursday,false] => Feb, March, Nov
[Friday,false] => Aug

to fill the table you have a generic month Jan(31),Feb(28).. and then iterate with a seed of each day of the week, noting months that start with sunday, and also with a leap year and without. Pretty straight forward, and once done, you can share it with us :)

nlucaroni
This is the fastest table method, afaict. There are fourteen types of weekdays - 7 for non leap years, 7 for leap years, and 12 months. A 2D or 3D array provides a very quick answer once you know what day of the week Jan 1 falls on, and whether it's a leap year - both are easy to calculate.
Adam Davis
+2  A: 

One thing I noticed is that the first of the month falls on a Sunday during months with a Friday the 13th. You can probably leverage this to make it easier to calculate.

R. Bemrose
+1  A: 

This is how I would do it:

  • Assume year is known and is an integer.

  • Loop from 1 to 12

    • Create date with loop index, year and 13 for the day

If you want to start with a month and year (you have to assume some sort of year), your algorithm becomes

  • Assume year is known and an integer

  • Assume month is known and is an integer

  • Loop

    • Create date with index of loop as year, known month variable, and 13 for the day

    • Determine day of week as per established algorithms

    • If day of week calculate above is Friday, return date, else

    • Else increment year by 1

casperOne
+3  A: 

Here's some example PHP code that goes through a pretty straight forward loop of the dates in a range. I would modify this to check the 13th of each month for Fridayness, rather than checking every Friday for 13thness, as they do in the example.

Bill the Lizard
Checking the 13th of each month is certainly the better way to go.
pezi_pink_squirrel
Yeah, seemed about 4X more efficient to me. :)
Bill the Lizard