RabbitFarm
2023-01-15
Multiple Goods
The examples used here are from the weekly challenge problem statement and demonstrate the working solution.
Part 1
You are given a list of integers, @list. Write a script to find the total count of Good airs.
Solution
use v5.36;
sub good_pairs{
my(@numbers) = @_;
my @pairs;
do{
my $i = $_;
do{
my $j = $_;
push @pairs, [$i, $j] if $numbers[$i] == $numbers[$j] && $i < $j;
} for 0 .. @numbers - 1;
} for 0 .. @numbers - 1;
return 0 + @pairs;
}
MAIN:{
say good_pairs 1, 2, 3, 1, 1, 3;
say good_pairs 1, 2, 3;
say good_pairs 1, 1, 1, 1;
}
Sample Run
$ perl perl/ch-1.pl
4
0
6
Notes
First off, a pair (i, j)
is called good if list[i] == list[j]
and i < j
. Secondly,
I have never written a nested loop with this mix of do
blocks and postfix for
, and
I am greatly entertained by it! Perl fans will know that it really isn't all that
different from the more standard looking do/while construct. A do
block is not really a
loop, although it can be repeated, and so you cannot use last
, redo
, or next
within
the block. But this is exactly the same case as within a map
, which is what we are
trying to replicate here, a map
in void context without actually using map
.
Imagine a nested map
, that is basically the same thing as this, but with the more clear
focus on side effects versus a return value.
Part 2
You are given an array of integers, @array and three integers $x,$y,$z. Write a script to find out total Good Triplets in the given array.
Solution
use v5.36;
use Math::Combinatorics;
sub good_triplets{
my($numbers, $x, $y, $z) = @_;
my $combinations = Math::Combinatorics->new(count => 3, data => [0 .. @{$numbers} - 1]);
my @combination = $combinations->next_combination;
my @good_triplets;
{
my($s, $t, $u) = @combination;
unless($s >= $t || $t >= $u || $s >= $u){
push @good_triplets, [@{$numbers}[$s, $t, $u]] if(abs($numbers->[$s] - $numbers->[$t]) <= $x &&
abs($numbers->[$t] - $numbers->[$u]) <= $y &&
abs($numbers->[$s] - $numbers->[$u]) <= $z);
}
@combination = $combinations->next_combination;
redo if @combination;
}
return 0 + @good_triplets;
}
MAIN:{
say good_triplets([3, 0, 1, 1, 9, 7], 7, 2, 3);
say good_triplets([1, 1, 2, 2, 3], 0, 0, 1);
}
Sample Run
$ perl perl/ch-2.pl
4
0
Notes
The approach here is the same that I used for the Magical Triples problem from TWC 187. The module Math::Combinatorics is used to generate all possible triples of indices. These are then filtered according to the criteria for good triplets.
References
posted at: 11:22 by: Adam Russell | path: /perl | permanent link to this entry