## Perl Weekly Challenge 227: Friday 13th

These are some answers to the Week 227, Task 1, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on July 30, 2023 at 23:59). This blog post offers some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

You are given a year number in the range 1753 to 9999.

Write a script to find out how many dates in the year are Friday 13th, assume that the current Gregorian calendar applies.

Example

``````Input: \$year = 2023
Output: 2

Since there are only 2 Friday 13th in the given year 2023 i.e. 13th Jan and 13th Oct.
``````

The Gregorian calendar is the calendar used in most parts of the world. It was introduced in October 1582 by Pope Gregory XIII as a modification of, and replacement for, the previously used Julian calendar. The main change was to space leap years differently.

Date calculations are notoriously cumbersome and error-prone. So we will rely on well-tested core modules, which can tell us whether a given date in history or in the future is a Friday or some other day of the week.

### Friday 13th in Raku

Raku has a built-in Date class that will compute the hard stuff for us. It has a `new` constructor that can take three parameters, year, month and day in the month, and return an immutable object (of type `Date`) identifying a day in the Gregorian calendar. It also has a `day-of-week` method, which returns an integer between 1 and 7, representing the day in the week (with Monday being 1 and Sunday being 7).

So, all we need to do for a given year is to check whether, for each month, the 13th falls on a Friday (`day-of week` == 5) and count how many times this happens in the year.

``````sub friday_13 (\$y) {
my \$count = 0;
for 1..12 -> \$m {
# For the Raku Date class, Friday is the
# 5th day of the week
\$count++ if Date.new(\$y, \$m, 13).day-of-week == 5;
}
return \$count;
}
for 1753, |(2023..2030), 9998 -> \$year {
say \$year, " => ", friday_13 \$year;
}
``````

This program displays the following output:

``````\$ raku ./friday13.raku
1753 => 2
2023 => 2
2024 => 2
2025 => 1
2026 => 3
2027 => 1
2028 => 1
2029 => 2
2030 => 2
9998 => 3
``````

### Friday 13th in Perl

There are very powerful date and time calculation modules on the CPAN, such as, especially DateTime by Dave Rolsky. However, it is not a core module and, for various reasons, I prefer to use a core module such as Time::Piece, although its documentation has some opportunities for improvement.

Here, we use the (POSIX-inspired) `strptime` method as a constructor and the `wday` method to find the day in the week of any given date.

Just as in Raku, all we need to do for a given year is to check whether, for each month, the 13th falls on a Friday (day of week == 6) and count how many times this happens. Note that, for `Time::Piece`, the week starts on Sunday and, therefore, the integer representing Friday is 6.

``````use strict;
use warnings;
use feature 'say';
use Time::Piece;

sub friday_13 {
my \$year = shift;
my \$count = 0;
my \$day = 13;
for my \$month (1..12) {
my \$dt = Time::Piece->strptime("\$month/\$day/\$year",
"%m/%d/%Y");
\$count++ if \$dt->wday == 6;   # Friday == 6th day
}
return \$count;
}
for my \$year (2023..2030, 9998) {
say \$year, " => ", friday_13 \$year;
}
``````

This program displays the following output:

``````2023 => 2
2024 => 2
2025 => 1
2026 => 3
2027 => 1
2028 => 1
2029 => 2
2030 => 2
9998 => 3
``````

Note that we haven't computed the number of Friday 13th for the year 1753, because it appears that the `Time::Piece` module can't handle such old dates.

## Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on August 6 , 2023. And, please, also spread the word about the Perl Weekly Challenge if you can.