With this PWC evoking “oddness”, the only music I could really use was David Bowie’s Space Oddity.
So let’s sit in our tin can far above the world and watch Perl Weekly Challenge 332 unfold.
Task 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"
Approach
This is pretty straightforward: split the string on "-"
into a list, then convert each of those numbers into the binary representation, then rejoin them. Easy peasy.
Raku
Ah, but what we get when we split isn’t a number, it’s a string. So we need to convert them to an integer first. Fortunately, the Str
class has a .Int
method to do that.
sub binaryDate($date) {
$date.split(/\-/).map({ .Int.base(2) }).join("-");
}
View the entire Raku script for this task on GitHub.
$ raku/ch-1.raku
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"
Perl
There’s probably a better way to convert a number into its binary form in Perl, but immediately my mind went to sprintf("%b")
. The great thing is Perl’s automatic type conversion meant I didn’t need to convert the string into an integer before passing it to sprintf
.
sub binaryDate($date) {
join "-", map { sprintf "%b", $_ } split /\-/, $date;
}
View the entire Perl script for this task on GitHub.
Python
Python proved to have a wrinkle:
>>> '-'.join([ bin(int(i)) for i in "2025-07-26".split('-')])
'0b11111101001-0b111-0b11010'
Those 0b
prefixes in front of each number.So I needed to lop them off.
def binary_date(date):
return '-'.join([ bin(int(i))[2:] for i in date.split('-')])
View the entire Python script for this task on GitHub.
Elixir
And Elixir had it’s own wrinkle. The function for converting an integer to it’s binary representation, Integer.digits/2
, doesn’t produce a string representation of the digits… it produces a List. Fortunately, piping the list through Enum.join/2
easily rejoins the list into a string.
But Elixir’s pipe operator (|>
) makes this easy to read: the string is split, and then we convert each part of the string to an integer from a string, then we convert each integer into its binary representation, and then we rejoin those with a "-"
.
def binary_date(date) do
date
|> String.split("-")
|> Enum.map(fn s -> String.to_integer(s) end)
|> Enum.map(fn i -> Integer.digits(i, 2) |> Enum.join end)
|> Enum.join("-")
end
View the entire Elixir script for this task on GitHub.
Task 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
Approach
Ooh! This is a Bag. We use the bag to count how often each letter appears, then check to see if those counts are even.
Raku
Again, I was able to chain these together: .comb
to split the string into its characters, .Bag
to populate an immutable Bag
object, then we call the .values
method to get the values (we don’t actually care about the keys, only whether they appear an odd or even amount of times:
sub oddLetters($str) {
for $str.comb.Bag.values -> $times {
return 'false' if $times % 2 == 0;
}
return 'true';
}
View the entire Raku script for this task on GitHub.
$ raku/ch-2.raku
Example 1:
Input: $str = "weekly"
Output: false
Example 2:
Input: $str = "perl"
Output: true
Example 3:
Input: $str = "challenge"
Output: false
Perl
In Perl, we have to implement the Bag as a hash…
sub oddLetters($str) {
my %letters;
map { $letters{$_}++ } split //, $str;
foreach my $times (values %letters) {
return 'false' if $times % 2 == 0;
}
return 'true';
}
View the entire Perl script for this task on GitHub.
Python
Once again, the Counter
datatype in the collections module is essentially the same as a Bag.
from collections import Counter
def odd_letters(str_val):
for k,v in Counter(list(str_val)).items():
if v % 2 == 0: return 'false'
return 'true'
View the entire Python script for this task on GitHub.
Elixir
I decided to borrow the function I wrote for PWC 283 to actually make the bag, which made the meat of this solution on line 22 really concise. And because I wanted to be able to bail on the loop through the values early if I encountered an even count, the easiest way to do that was to implement a recursive all_odd
function that checks the first element of the list, and if it’s even, returns “false”, and then passes the rest of the list to itself, and if there’s no elements left, it returns “true”.
def make_bag(list) do
{_, bag} = Enum.map_reduce(list, %{}, fn i, bag ->
{ i, Map.put(bag, i, Map.get(bag, i, 0) + 1) }
end)
bag
end
def all_odd([]), do: "true"
def all_odd([this | rest]) do
if rem(this,2) == 0 do
"false"
else
all_odd(rest)
end
end
def odd_letters(str) do
str |> String.graphemes |> make_bag |> Map.values |> all_odd
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-332/packy-anderson