Perl Weekly Challenge 244: Group Hero
These are some answers to the Week 244, Task 2, of the Perl Weekly Challenge organized by Mohammad S. Anwar.
Spoiler Alert: This weekly challenge deadline is due in a few days from now (on November 26, 2023 at 23:59). This blog post offers some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.
Task 2: Group Hero
You are given an array of integers representing the strength.
Write a script to return the sum of the powers of all possible combinations; power is defined as the square of the largest number in a sequence, multiplied by the smallest.
Example 1
Input: @nums = (2, 1, 4)
Output: 141
Group 1: (2) => square(max(2)) * min(2) => 4 * 2 => 8
Group 2: (1) => square(max(1)) * min(1) => 1 * 1 => 1
Group 3: (4) => square(max(4)) * min(4) => 16 * 4 => 64
Group 4: (2,1) => square(max(2,1)) * min(2,1) => 4 * 1 => 4
Group 5: (2,4) => square(max(2,4)) * min(2,4) => 16 * 2 => 32
Group 6: (1,4) => square(max(1,4)) * min(1,4) => 16 * 1 => 16
Group 7: (2,1,4) => square(max(2,1,4)) * min(2,1,4) => 16 * 1 => 16
Sum: 8 + 1 + 64 + 4 + 32 + 16 + 16 => 141
Group Hero in Raku
This task is fairly straight forward in Raku, using the built-in combinations, max, and min methods. Note that we also use the built-in postfix ²
operator to find the square of a number.
sub group-hero (@in) {
my $sum = 0;
for @in.combinations: 1..@in.elems -> @comb {
$sum += @comb.max² * @comb.min;
}
return $sum;
}
for <2 1 4>, <4 1 5 2> -> @test {
printf "%-10s => ", "@test[]";
say group-hero @test;
}
This program displays the following output:
$ raku ./group-hero.raku 7
2 1 4 => 141
4 1 5 2 => 566
Group Hero in Perl
Here, we cannot port simply the Raku program to Perl, because Perl lacks the combinations
, max
, and min
functions. As I stated many times, I eschew using on-the-shelf modules in coding challenge, because using ready-made products is not the essence of a challenge (but I would of course do so in real life programming). We are looking for combinations, but are actually using only pairs of items for calculations. So, I decided to first sort the input array and hand-pick the first and last items of any combination.
use strict;
use warnings;
use feature 'say';
sub group_hero {
# Caution: this works only with input arrays of 3 items
my @in = sort { $a <=> $b } @_;
my $sum = 0;
$sum += $_ * $_ * $_ for @in;
my ($i, $j) = (0, 0);
for $j (0..$#in) {
for $i (1..$#in) { #gap
next unless defined $in[$j + $i];
$sum += $in[$j] * $in[$j + $i] * $in[$j + $i];
}
}
$sum += $in[0] * $in[$#in] * $in[$#in];
return $sum;
}
for my $test ([<2 1 4>]) {
printf "%-10s => ", "@$test";
say group_hero @$test;
}
This works well with input arrays of three items:
$ perl ./group-hero.pl
2 1 4 => 141
but this wouldn't work with arrays having more than three elements. As I don't have time right now to solve this issue, I'll leave it at that, and may come back to it later if I find the time to suggest a better more generic solution. Three nested loops (instead of two) should probably do the trick, and it shouldn't be too difficult, but I can't do it today. Later this week if possible.
Wrapping up
The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on December 3, 2023. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment