Perl Weekly Challenge: Week 160

Challenge 1:

Four is Magic

You are given a positive number, $n < 10.

Write a script to generate english text sequence starting with the English cardinal representation of the given number, the word ‘is’ and then the English cardinal representation of the count of characters that made up the first word, followed by a comma. Continue until you reach four.

Example 1:
Input: $n = 5
Output: Five is four, four is magic.
Example 2:
Input: $n = 7
Output: Seven is five, five is four, four is magic.
Example 3:
Input: $n = 6
Output: Six is three, three is five, five is four, four is magic.

To solve this challenge in Raku, first we need to set up a correspondence between numbers and their textual representation.

my %words = (
    1  => 'one',
    2  => 'two',
    3  => 'three',
    4  => 'four',
    5  => 'five',
    6  => 'six',
    7  => 'seven',
    8  => 'eight',
    9  => 'nine',
);

Then given the input $n, we find the word that corresponds to it.

my $first = %words{$n};

Now we just loop...

loop {
    if $first eq 'four' {

... until we have a arrived at the number four. In this case we print "four is magic" and exit the loop.

        say "four is magic.";
        last;
    } else {

If the number was not four, we have to find the word that matches the number of characters in the word contained in $first. This value I assigned to a variable imaginatively named $second.

        my $second = %words{$first.chars};

We print the values of $first and $second in the proper format.

        print "$first is $second, ";

Then $second becomes the new $first and the next iteration of loop takes place.

        $first = $second;
    }
}

(Full code on Github.)

Perl works the same way with only minor syntactic differences.

my %words = (
    1  => 'one',
    2  => 'two',
    3  => 'three',
    4  => 'four',
    5  => 'five',
    6  => 'six',
    7  => 'seven',
    8  => 'eight',
    9  => 'nine',
);

my $first = $words{$n};
while(1) {
    if ($first eq 'four') {
        say "four is magic.";
        last;
    } else {
        my $second = $words{length $first};
        print "$first is $second, ";
        $first = $second;
    }
}

(Full code on Github.)

Challenge 2:

Equilibrium Index

You are give an array of integers, @n.

Write a script to find out the Equilibrium Index of the given array, if found.

For an array A consisting n elements, index i is an equilibrium index if the sum of elements of subarray A[0 ... i-1] is equal to the sum of elements of subarray A[i+1 ... n-1].

Example 1:
Input: @n = (1, 3, 5, 7, 9)
Output: 3
Example 2:
Input: @n = (1, 2, 3, 4, 5)
Output: -1 as no Equilibrium Index found.
Example 3:
Input: @n = (2, 4, 2)
Output: 1

This one is a little bit awkward-looking syntactically but quite simple really.

For each element of the input array...

for 0 ..^ @n.elems -> $i {

...we compute the sum of the elements before it and the sum of the elements after it. The two parts of the array are expressed as array slices or ranges of indices.

    if ([+] @n[0 ..^ $i]) == ([+] @n[$i ^..^ @n.elems]) {

If the two sums are equal, we print the index of the middle element and exit the program. say $i; exit; }

If not, we try the next element.

}

If we have tries all the elements and not found equal sums, there is not equilibrium index so we just print -1.

say -1;

(Full code on Github.)

For Perl I had to replace the use of [+] with my tried and true sum() function and it took me a couple of tries to get the array slice syntax correct.

for my $i (0 .. (scalar @n - 1)) {
    if (sum([@n[0 .. $i - 1]]) == sum([@n[$i + 1 .. scalar @n - 1]])) {
        say $i;
        exit;
    }
}

say -1;

(Full code on Github.)