Perl Weekly Challenge: Week 2
This weeks problems in the Perl Weekly Challenge were a little bit harder than last weeks but still well within my comfort zone I'm happy to report.
Challenge 1:
Write a script or one-liner to remove leading zeros from positive numbers.
My answer in Perl5 was:
perl -E 'say sprintf("%0d", shift)'
The same thing in Perl6 is:
perl6 -e 'sprintf("%0d", @*ARGS[0]).say'
Challenge 2:
Write a script that can convert integers to and from a base35 representation, using the characters 0-9 and A-Y. Dave Jacoby came up with nice description about base35, in case you needed some background.
This was a bit more involved. Here is the relevant parts of the code.
sub fromBase35 {
my ($number) = @_;
my $scale = (length $number) - 1;
my %digits;
@digits{(0 .. 9, 'A' .. 'Y')} = 0 .. 34;
my $result;
for my $digit (split '', $number) {
my $base10 = $digits{uc $digit} // die "malformed base-35 number\n";
$result += $base10 * 35 ** $scale;
$scale--;
}
return $result;
}
sub toBase35 {
my ($number) = @_;
my @digits = (0 .. 9, 'A' .. 'Y');
my @result;
while ($number > 34) {
my $digit = int($number / 35);
push @result, $digits[$digit];
$number -= ($digit * 35);
}
push @result, $digits[$number];
return join '', @result;
}
Perl6 has base conversion built in to its String and Real classes so I didn't have to bother coding it myself.
#!/usr/bin/perl6
# Thanks to ugexe on #perl6 for help with option parsing.
multi sub MAIN (
$number, #= the number to convert
Bool :$f! where .so #= convert base 35 number to base 10
) {
say $number.parse-base(35);
}
multi sub MAIN (
$number,
Bool :$t! where .so #= convert base 10 number to base 35
) {
say $number.base(35);
}
The only interesting thing here is the option handling. Like in the Perl5
version, I wanted to be able to specify -f and -t as options to the
script. You will notice there are two subroutines called MAIN. Perl6, like
C++, allows for multiple dispatch based on a functions signature. the -f
and -t will automatically get converted to arguments to MAIN called $f
and $t respectively so we can uses those to differentiate the signatures of
the two MAINs.
where .so is a constraint that makes sure the argument, which would
otherwise be a Str is converted to a Bool value.
the trailing ! marks this as a mandatory argument. As a positional parameter
$number is mandatory by default though we could change that with a trailing ?
(i.e. $number?) or by providing a default value (i.e $number = 0.)
I had a few problems getting this set up but ugexe on IRC (#perl6 on irc.freenode.net) helped me understand what to do.
Another nifty Perl6 feature for scripts is autogenerating a usage message like
the one I had to write myself for the Perl5 version. A basic description for
each option is also generated but you can customize it further by providing
a Perl6 POD comment (the #= construct) with your own description.