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.

Example
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.

Example
Input: $name = "Katie"
Output:

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

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.)