Perl Weekly Challenge: Week 105

Challenge 1:

Nth Root

You are given positive numbers $N and $k.

Write a script to find out the $Nth root of $k. For more information, please take a look at the wiki page.

Input: $N = 5, $k = 248832
Output: 12

Input: $N = 5, $k = 34
Output: 2.02

For once a math problem I actually knew how to do. Here's my Raku solution.

sub MAIN(
    Int $N, #= root
    Int $k  #= number
) {
    say ($k ** (1.0 / $N)).round(0.01);

(Full code on Github.)

Originally, I didn't have the call to .round() at the end and as a result for the first example I actually got 12.000000000000002, an unfortunate side effect of the inability of binary computers to represent decimal arithmetic. And for the second example I got 2.024397458499885. That's why I decided to round to 2 decimal places.

Perl doesn't have a builtin round function in its' library (though it gives the proper answer for the first example anyway.) so I had to use the Math::Round module. This is the relevant code.

say nearest(0.01, $k ** (1.0 / $N));

(Full code on Github.)

As you can see, the actual function I used was nearest() not round() which only works on integers.

Challenge 2:

The Name Game

You are given a $name.

Write a script to display the lyrics to the Shirley Ellis song The Name Game. Please checkout the wiki page for more information.

Input: $name = "Katie"

    Katie, Katie, bo-batie,
    Bonana-fanna fo-fatie
    Fee fi mo-matie

This was a fun one.

sub MAIN(
    Str $name,
) {
    my $stem = $name.subst(/^ <-[AaEeIiOoUu]> /, q{}).lc;

The first step is to strip off the first consonant from the $name. For good measure the resulting $stem is converted to lower case.

    my Bool $labial = $name.match(/^ <[BbFfMm]> /).Bool;
    say "$name, $name, bo-", $labial ?? q{} !! 'b', "$stem";
    say "Bonana-fana fo-", $labial ?? q{} !! 'f', "$stem";
    say "Fee fi mo-", $labial ?? q{} !! 'm', "$stem";
    say "$name!";

Now we just print the verse adding what linguists call labial sounds onto $stem to make a rhyme for the $name. There is an exception though. If the $name begins with b, f, or m, the labial is not added. So before printing the verse we check for an initial b, f, or m and assign a boolean to indicate whether we have it or not. And we use it to control the printing.


(Full code on Github.)

The perl version is slightly more verbose but works the same way.

my ($name) = @ARGV;
my $stem = $name;
$stem =~ s/^ [^AaEeIiOoUu] //msx;
$stem = lc $stem;

my $labial = $name =~ / ^ ([BbFfMm]) /msx;
say "$name, $name, bo-", ($labial ? q{} : 'b'), "$stem";
say "Bonana-fana fo-", ($labial ? q{} : 'f'), "$stem";
say "Fee fi mo-", ($labial ? q{} : 'm'), "$stem";
say "$name!";

(Full code on Github.)