Perl Weekly Challenge: Week 245

I have been missing in action for December for several reasons. First, I actually end up working more than usual during Christmas/New years so that my Christian colleagues can take time off to be with their families and I can have the flexibility to take my preferred holidays later on. Second I've moved after 25 years to a new place. Not too far away from my old apartment but moves always cause chaos. And whatever time was left after all that was spent doing Advent of Code. This year once again, I tried solving the problems in Raku (and a few in Kotlin too.) Sadly I only managed 13 of the 25 days with another 5 where I think I know what to do but haven't written the code yet. I'll try and finish them all off sometime this month.

Anyway, on to this weeks challenge...

Challenge 1:

Sort Language

You are given two array of languages and its popularity.

Write a script to sort the language based on popularity.

Example 1
Input: @lang = ('perl', 'c', 'python')
       @popularity = (2, 1, 3)
Output: ('c', 'perl', 'python')
Example 2
Input: @lang = ('c++', 'haskell', 'java')
       @popularity = (1, 3, 2)
Output: ('c++', 'java', 'haskell')

Feeling a bit lazy, I just hardcoded the example input into my solution. MAIN() just takes that input and uses it as parameters to sortLanguages(), a function which does all the work of sorting.

sub sortLanguages(@lang, @popularity) {

@lang and @popularity are used to create a hash wheres the keys are languages and the values are their popularity scores. This is done in one fell swoop with the Z=> operator.

    my %ranking = @lang Z=> @popularity;

Then all that needs to be done is to sort the hash by its values and return the keys in sorted order.

    return %ranking.keys.sort({ %ranking{$^a} <=> %ranking{$^b}});
}

(Full code on Github.)

This is sortLanguages() in Perl.

sub sortLanguages {

The input arrays are passed by reference.

    my ($lang, $popularity) = @_;
    my %ranking;

Because we don't have Z=>, the hash has to be populated the old-fashioned way.

    for my $i (0 .. scalar @{$lang} - 1) {
        $ranking{$lang->[$i]} = $popularity->[$i];
    }

    return sort { $ranking{$a} <=> $ranking{$b}} keys %ranking;
}

(Full code on Github.)

Challenge 2:

Largest of Three

You are given an array of integers >= 0.

Write a script to return the largest number formed by concatenating some of the given integers in any order which is also multiple of 3. Return -1 if none found.

Example 1
Input: @ints = (8, 1, 9)
Output: 981

981 % 3 == 0
Example 2
Input: @ints = (8, 6, 7, 1, 0)
Output: 8760
Example 2
Input: @ints = (1)
Output: -1

We start by assigning a variable to hold the result. It is initialized to -1 which will be the result if no largest number is found.

my $max = -1;

Then we find every combination of three or more digits from the input and loop through them. This is straightforward using the .combinations() method with one caveat...

for @ints.combinations(3 .. @ints.elems) -> $combo {

...combinations() gives you groups of digits but it won't give you every permutation of those digits. For that you need the aptly named .permutations() method. I tried to combine this with the previous line but it didn't quite work so I gave up. I did however combine it with .map() and .grep() to filter those permutations which, when joined together, are divisible by three.

    for @$combo.permutations().map({ $_.join }).grep({ $_ %% 3 }) -> $perm  {

If the joined permutation is greater than the current max value, it becomes the new max value.

        if $perm > $max {
            $max = $perm;
        }
    }
}

Finally, the max value is printed.

say $max;

(Full code on Github.)

For the Perl version we need replacements for .combinations() and .permutations() but they are just a simple copy and paste away from previous challenges.

my $max = -1;

Because my combinations() routine doesn't support ranges, an extra loop is needed.

for my $elems (3 .. (scalar @ARGV)) {
    for my $combo (combinations(\@ARGV, $elems)) {
        my @permutations;
        permute { push @permutations, \@_; } @{$combo};
        for my $perm (grep { $_ % 3 == 0 } map { join q{}, @{$_} } @permutations) { 
            if ($perm > $max) {
                $max = $perm;
            }
        }
    }
}

say $max;

(Full code on Github.)