Perl Weekly Challenge: Week 332
Challenge 1:
Binary Date
You are given a date in the format
YYYY-MM-DD
.Write a script to convert it into binary date.
Example 1
Input: $date = "2025-07-26"
Output: "11111101001-111-11010"
Example 2
Input: $date = "2000-02-02"
Output: "11111010000-10-10"
Example 3
Input: $date = "2024-12-31"
Output: "11111101000-1100-11111"
This challenge can done as a one-liner. We take the first command-line argument (@*ARGS[0]
) and
.split()
it into segments at -
characters. Then, using .map()
we convert each of those segments
into numbers with .Int()
and then into binary numbers with .base(2)
. The -
separators are then reinserted
when the segments are .join()
ed up into one string again and the result is printed with .say()
.
@*ARGS[0].split(q{-}).map({$_.Int.base(2)}).join(q{-}).say
Perl can also do this in one line. However we have to use sprintf()
to do the binary conversion.
say join q{-}, (map {sprintf "%b", $_} split /-/, shift)
Challenge 2:
Odd Letters
You are given a string.
Write a script to find out if each letter in the given string appeared odd number of times.
Example 1
Input: $str = "weekly"
Output: false
w: 1 time
e: 2 times
k: 1 time
l: 1 time
y: 1 time
The letter 'e' appeared 2 times i.e. even.
Example 2
Input: $str = "perl"
Output: true
Example 3
Input: $source = "challenge"
Output: false
This is also one line in Raku though perhaps a little unintuitive to understand. I would definitely comment this meticulously if it was production code.
We start once again with retrieving the input string from the first command-line argument. This is split
into a Sequence
of characters with .comb()
and then converted into a Bag
with .Bag()
. A Bag
is somewhat
like a std::unordered_multiset
in C++. Its' keys are the letters in the input, and values, the number of times
each key occurs. Now the complicated bit; the values of this Bag
is compared to a test condition in an all junction
, The condition is %% 2
i.e. what is the remainder if the value is divided by two? For an even number,
by definition it's going to be 0 which converts to False
. For odd numbers, the remainder will be 1 which converts
to True
. So we will have a List
of True
or False
elements. all
will return all(True)
if and only if all
elements of the list are True
which will only be the case if all the values of the Bag
are odd. Otherwise it
returns all(False)
. .so()
enforces Boolean context making the answer True
or False
which is then printed
out by .say()
.
all(@*ARGS[0].comb.Bag.values %% 2).so.say
In Perl we don't have Bag
s or junction
s so we have to try a different and longer approach.
As in Raku, the input is split()
up into individual letters.
my @letters = split //, $str;
A Hash
stores the letters as keys and their frequency as values.
my %count;
%count
is populated in this loop.
for my $letter (@letters) {
$count{$letter}++;
}
Now in a second loop, the values of %count
are examined and if one should prove to be even, False
will be
output and the script will end.
for my $n (values %count) {
if ($n % 2 == 0) {
say "False";
exit;
}
}
If we reach the end of the loop, it means all the values were odd so we print True
.
say "True";