RabbitFarm

2025-06-22

The Day We Decompress

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1: Day of the Year

You are given a date in the format YYYY-MM-DD. Write a script to find day number of the year that the given date represent.

The core of the solution is contained in a main loop. The resulting code can be contained in a single file.

"ch-1.pl" 1


use v5.40;
compute the day of the year 2
main 4

The answer is arrived at via a fairly straightforward calculation.

compute the day of the year 2 ⟩≡


sub day_of_year {
my ($date) = @_;
my $day_of_year = 0;
my ($year, $month, $day) = split /-/, $date;
determine if this is a leap year 3
my @days_in_month = (31, $february_days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
$day_of_year += $days_in_month[$_] for (0 .. $month - 2);
$day_of_year += $day;
return $day_of_year;
}

Fragment referenced in 1.

Defines: $year 3.

Uses: $february_days 3.

Let’s break the logic for computing a leap year into it’s own section. A leap year occurs every 4 years, except for years that are divisible by 100, unless they are also divisible by 400.

determine if this is a leap year 3 ⟩≡


my $is_leap_year = ($year % 400 == 0) || ($year % 4 == 0 && $year % 100 != 0);
my $february_days = $is_leap_year ? 29 : 28;

Fragment referenced in 2.

Defines: $february_days 2, $is_leap_year Never used.

Uses: $year 2.

Just to make sure things work as expected we’ll define a few short tests. The double chop is just a lazy way to make sure there aren’t any trailing commas in the output.

main 4 ⟩≡


MAIN:{
say day_of_year q/2025-02-02/;
say day_of_year q/2025-04-10/;
say day_of_year q/2025-09-07/;
}

Fragment referenced in 1.

Sample Run
$ perl perl/ch-1.pl 
33 
100 
250
    

Part 2: Decompressed List

You are given an array of positive integers having even elements. Write a script to to return the decompress list. To decompress, pick adjacent pair (i, j) and replace it with j, i times.

For fun let’s use recursion!

"ch-2.pl" 5


use v5.40;
decompress list 6
main 7

Sometimes when I write a recursive subroutine in Perl I use a reference variable to set the return value. Other times I just use an ordinary return. In some cases, for convenience, I’ll do this with two subroutines. One of these is a wrapper which calls the main recursion.

For this problem I’ll do something a little different. I’ll have one subroutine and for each recursive call I’ll add in an array reference to hold the accumulating return value.

Note that we take advantage of Perl’s automatic list flattening when pushing to the array reference holding the new list we are building.

decompress list 6 ⟩≡


sub decompress_list{
my $r = shift @_;
if(!ref($r) || ref($r) ne q/ARRAY/){
unshift @_, $r;
$r = [];
}
unless(@_ == 0){
my $i = shift @_;
my $j = shift @_;
push @{$r}, ($j) x $i;
decompress_list($r, @_);
}
else{
return @{$r};
}
}

Fragment referenced in 5.

The main section is just some basic tests.

main 7 ⟩≡


MAIN:{
say join q/, /, decompress_list 1, 3, 2, 4;
say join q/, /, decompress_list 1, 1, 2, 2;
say join q/, /, decompress_list 3, 1, 3, 2;
}

Fragment referenced in 5.

Sample Run
$ perl perl/ch-2.pl 
3, 4, 4 
1, 2, 2 
1, 1, 1, 2, 2, 2
    

References

The Weekly Challenge 326
Generated Code

posted at: 16:45 by: Adam Russell | path: /perl | permanent link to this entry