Inspired by a code golf question on codegolf.stackexchange.com asking for code that counted the number of Friday 13ths in a year I came up with this inefficient NodeJS/JavaScript solution. Both the solutions below can be dropped into a .js file and run from the command line by NodeJS.
Someone else came up with another JavaScript solution which takes advantage of some of the idiosyncrasies of JavaScript which I thought was interesting:
Here are the interesting parts:
// To run: // node friday13.js <2013> // <2013> is the year which you want a count of Friday 13ths in // Add a day incrementer to the Date prototype Date.prototype.addDays = function (num) { var value = this.valueOf(); value += 86400000 * num; return new Date(value); } var year = process.argv[2]; if(!year){ console.log('Was year the first param? Received: ' + year); return; } var startDate = new Date(year,0,1); console.log(startDate); var endDate = new Date(year,11,31); console.log(endDate); var counter = 0; while(startDate <= endDate) { if(startDate.getDay() === 5 && startDate.getDate() === 13) { counter++; } startDate = startDate.addDays(1); } console.log(counter + ' Friday 13ths in ' + year);
Someone else came up with another JavaScript solution which takes advantage of some of the idiosyncrasies of JavaScript which I thought was interesting:
var year = process.argv[2]; var numFridays = function(year) { var count=0; for(month=12;month--;) { count += !new Date(year,month,1).getDay(); } return count; } console.log('Number: ' + numFridays(year));
Here are the interesting parts:
- The for loop on line 5 relies on the fact that when the value of month hits zero it will evaluate to false.
- On line 5 month will be evaluated for truthiness before it's decremented and that it will be decremented before the body of the for loop is evaluated.
- We only have to loop through the 12 months of the year as there can only be one Friday 13th in each month so no need to go through every day.
- The JavaScript getDay() method of the Date object returns a 0 for Sunday, 1 for Monday etc. If the month has a Friday 13th then by definition the first day of the month is a Sunday. i.e. if the value of getDay() on the 1st of the month is 0 (equivalent to false) then count this month. To do that we ! (not) the return value which gives us true which will evaluate as the value of 1 when added to an integer.
The second one seems like it's trying hard to be clever. I'm not a fan of relying on side effects that could change some day nor do I like having to step through several times to understand what is happening. I changed the significant line to the following, which I think is much clearer:
ReplyDeletecount += (new Date(year, month, 13).getDay() === 5) ? 1 : 0;