Looking at this week’s challenge, the “date” aspect jumped out at me, and I thought of a an old song… Got a Date With an Angel.
So let’s get on our way to heaven with Perl Weekly Challenge 326.
Task 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.
Example 1
Input: $date = '2025-02-02'
Output: 33
The 2nd Feb, 2025 is the 33rd day of the year.
Example 2
Input: $date = '2025-04-10'
Output: 100
Example 3
Input: $date = '2025-09-07'
Output: 250
Approach
When I saw this as a problem, my first thought was “This is a method in every decent DateTime module. Does Mohammed want us to roll our own?” Then my immediate next thought was of the infamous “Falsehoods Programmers Believe About Time” article, and I said to myself “No. I write these solutions not to prove how clever a programmer I am, I write them to show how easy these languages are to solve problems in.” There’s nothing gained by trying to implement this by what? Doing what I did for PWC 227 and starting with the first day of the year and incrementing until I get to the target date? So here’s the really short answers.
Raku
In Raku, the day-of-year
method from the Datish
role does the work.
Date.new($date).day-of-year;
View the entire Raku script for this task on GitHub.
$ raku/ch-1.raku
Example 1:
Input: $date = '2025-02-02'
Output: 33
Example 2:
Input: $date = '2025-04-10'
Output: 100
Example 3:
Input: $date = '2025-09-07'
Output: 250
Perl
In Perl, we use the core module Time::Piece
. We add one to the result because, according to the documentation, 0 = Jan 01
.
use Time::Piece;
Time::Piece->strptime($date, "%Y-%m-%d")
->truncate(to => 'day')
->day_of_year + 1;
View the entire Perl script for this task on GitHub.
Python
In Python, we load the datetime
module. There isn’t a method to get the day of the year from that, but the strftime
method supports the %j
directive (as the 1989 C standard requires). But this returns a “zero-padded decimal number” (a string, really), so I’m pushing it through int()
to get rid of those zeros.
from datetime import date
int(date.fromisoformat(dateStr).strftime('%j'))
View the entire Python script for this task on GitHub.
Elixir
In Elixir, it’s all done by the Date
stuct, and its functions from_iso8601!/2
and day_of_year/1
.
Date.from_iso8601!(dateStr) |> Date.day_of_year
View the entire Elixir script for this task on GitHub.
Task 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.
Example 1
Input: @ints = (1, 3, 2, 4)
Output: (3, 4, 4)
Pair 1: (1, 3) => 3 one time => (3)
Pair 2: (2, 4) => 4 two times => (4, 4)=
Example 2
Input: @ints = (1, 1, 2, 2)
Output: (1, 2, 2)
Pair 1: (1, 1) => 1 one time => (1)
Pair 2: (2, 2) => 2 two times => (2, 2)
Example 3
Input: @ints = (3, 1, 3, 2)
Output: (1, 1, 1, 2, 2, 2)
Pair 1: (3, 1) => 1 three times => (1, 1, 1)
Pair 2: (3, 2) => 2 three times => (2, 2, 2)
Approach
This is a pretty easy problem, especially when there are operators to do most of the work.
Raku
In Raku, there’s the list repetition operator (xx
). And we can also show off processing a list by pairs.
sub decompress(@ints) {
my @out;
for @ints -> $i, $j {
@out.append($j xx $i);
}
@out
}
View the entire Raku script for this task on GitHub.
$ raku/ch-2.raku
Example 1:
Input: @ints = (1, 3, 2, 4)
Output: (3, 4, 4)
Example 2:
Input: @ints = (1, 1, 2, 2)
Output: (1, 2, 2)
Example 3:
Input: @ints = (3, 1, 3, 2)
Output: (1, 1, 1, 2, 2, 2)
Perl
I keep forgetting that the x
operator in Perl can not only be used to do string repetition, but if the x
is in list context, and the left operand is either enclosed in parentheses or a qw//
list, it performs a list repetition!
sub decompress(@ints) {
my @out;
for my ($i, $j) ( @ints ) {
push @out, ($j) x $i;
}
@out
}
View the entire Perl script for this task on GitHub.
Python
In Python, version 3.12 added the batched
function to itertools
, which was a good enough reason for me to do a pyenv install 3.13.0
, since I’ve been using 3.10.4 for much too long. However, this produces nested arrays, so to flatten them, I needed itertools
‘ chain.from_iterable
.
def decompress(ints):
out = []
for i, j in batched(ints, 2):
out.append([j] * i)
return list(chain.from_iterable(out))
View the entire Python script for this task on GitHub.
Elixir
As always, recursion is doing the looping. List.pop_at/3
is pulling the elements off the list, and List.duplicate/2
is doing the list repetition.
def decompress([], out), do: out
def decompress(ints, out) do
{i, ints} = List.pop_at(ints, 0)
{j, ints} = List.pop_at(ints, 0)
decompress(ints, out ++ List.duplicate(j, i))
end
def decompress(ints) do
decompress(ints, [])
end
View the entire Elixir script for this task on GitHub.
Here’s all my solutions in GItHub: https://github.com/packy/perlweeklychallenge-club/tree/master/challenge-326/packy-anderson