The Task 1 of the Weekly Challenge 227 is the following:
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.
Let us solve it in the Raku programming language.
The idea is is to loop over the months of the given year and to count the Fridays which happen to be the 13th.
sub count-friday-the13s($year) { my $count = 0; for 1..12 -> $month { my $dt = DateTime.new( year => $year, month => $month, day => 13 ); $count++ if $dt.day-of-week == 5; } return $count; }
The code is very clear and explains itself. The result for 2023 is 2 as it should be:
say count-friday-the13s(2023); # 2
Now, let us compactify the code to make it more readable 🙂
sub count-friday-the13s($year) { [+] map { 5 == DateTime.new( year => $year, month => $_, day => 13).day-of-week }, 1..12; }
The loop is now replaced with map
, and adding up the Trues is done using a reduction metaoperation [+]
. There is no explicit return
keyword, as Raku will use the last computed value as the result of the function call.
Finally, after we have a compact solution, we can return to the task description and discover that the sample output also lists the dates, not only the counter.
So, there’s nothing to do as to return to a more verbose solution and collect the dates too. So, back to explicit loops, and here’s the final solution:
my $year = @*ARGS[0] // 2023; my @dates; for 1..12 -> $month { my $dt = DateTime.new(year => $year, month => $month, day => 13); if ($dt.day-of-week == 5) { push @dates, $dt; } } if @dates { my $count = @dates.elems; if $count == 1 { say "There is only one Friday the 13th in $year:"; } else { say "There are {@dates.elems} Fridays the 13th in $year:"; } .mm-dd-yyyy.say for @dates; } else { say "There are no Friday the 13th in $year."; }
The output for a sample year selection:
$ raku ch-1.raku There are 2 Fridays the 13th in 2023: 01-13-2023 10-13-2023 $ raku ch-1.raku 2023 There are 2 Fridays the 13th in 2023: 01-13-2023 10-13-2023 $ raku ch-1.raku 2021 There is only one Friday the 13th in 2021: 08-13-2021 $ raku ch-1.raku 2022 There is only one Friday the 13th in 2022: 05-13-2022 $ raku ch-1.raku 2024 There are 2 Fridays the 13th in 2024: 09-13-2024 12-13-2024 $ raku ch-1.raku 2025 There is only one Friday the 13th in 2025: 06-13-2025
I reached for a Junction with :
sub friday13 ( $year ) {
elems gather .take if .day-of-week == 5
for Date.new( $year, ( 1 .. 12 ).any, 13 )
}