Perl Weekly Challenge 188: Divisible Pairs and Total Zero
These are some answers to the Week 188 of the Perl Weekly Challenge organized by Mohammad S. Anwar.
Task 1: Divisible Pairs
You are given list of integers @list
of size $n
and divisor $k
.
Write a script to find out count of pairs in the given list that satisfies the following rules.
The pair (i, j) is eligible if and only if
a) 0 <= i < j < len(list)
b) list[i] + list[j] is divisible by k
Example 1
Input: @list = (4, 5, 1, 6), $k = 2
Output: 2
Example 2
Input: @list = (1, 2, 3, 4), $k = 2
Output: 2
Example 3
Input: @list = (1, 3, 4, 5), $k = 3
Output: 2
Example 4
Input: @list = (5, 1, 2, 3), $k = 4
Output: 2
Example 5
Input: @list = (7, 2, 4, 5), $k = 4
Output: 1
Divisible Pairs in Raku
We use 2-item combinations of indice between 0 and the index of the last item of the list to satisfy rule (a). Then we increment $count
if the sum of the two items is divisible by the input divisor.
for (2, <4 5 1 6>), (2, <1 2 3 4>),
(3, <1 3 4 5>), (4, <5 1 2 3>),
(4, <7 2 4 5>), (2, < 1 2 3 4 5 6 7 >)
-> ($k, @test) {
my $count = 0;
for (0..@test.end).combinations(2) -> @comb {
$count++ if (@test[@comb[0]] + @test[@comb[1]]) %% $k;
}
say "$k (@test[]) -> ", $count;
}
This script displays the following output:
$ raku ./divisible-pairs.raku
2 (4 5 1 6) -> 2
2 (1 2 3 4) -> 2
3 (1 3 4 5) -> 2
4 (5 1 2 3) -> 2
4 (7 2 4 5) -> 1
2 (1 2 3 4 5 6 7) -> 9
Divisible Pairs in Perl
This is essentially the same approach as the Raku program above, except that we generate the combinations with two nested for
loops.
use strict;
use warnings;
use feature qw/say/;
for my $test ([2, [<4 5 1 6>]], [2, [<1 2 3 4>]],
[3, [<1 3 4 5>]], [4, [<5 1 2 3>]],
[4, [<7 2 4 5>]], [2, [< 1 2 3 4 5 6 7 >]]) {
my $k = $test->[0];
my @list = @{$test->[1]};
my $count = 0;
for my $i (0..$#list) {
for my $j (($i+1) .. $#list) {
++$count if ($list[$i] + $list[$j]) % $k == 0;
}
}
say "$k (@list) -> ", $count;
}
This script displays the following output:
$ perl ./divisible-pairs.pl
2 (4 5 1 6) -> 2
2 (1 2 3 4) -> 2
3 (1 3 4 5) -> 2
4 (5 1 2 3) -> 2
4 (7 2 4 5) -> 1
2 (1 2 3 4 5 6 7) -> 9
Task 2: Total Zero
You are given two positive integers $x
and $y
.
Write a script to find out the number of operations needed to make both ZERO. Each operation is made up either of the followings:
$x = $x - $y if $x >= $y
or
$y = $y - $x if $y >= $x (using the original value of $x)
Example 1
Input: $x = 5, $y = 4
Output: 5
Example 2
Input: $x = 4, $y = 6
Output: 3
Example 3
Input: $x = 2, $y = 5
Output: 4
Example 4
Input: $x = 3, $y = 1
Output: 3
Example 5
Input: $x = 7, $y = 4
Output: 5
This problem could certainly be solved with simple mathematical analysis, but I suspect we might end up with enough edge cases to make the program more complicated than a simple brute-force approach, i.e. iteratively computing the successive values of $x
and $y
.
Total Zero in Raku
sub to-zero ($x, $y) {
return $x >= $y ?? ($x - $y, $y) !! ($x, $y - $x);
}
for <5 4>, <4 6>, <2 5>, <3 1>, <7 4>, <9 1> -> @test {
my ($x, $y) = @test;
my $count = 0;
while ($x and $y ) {
($x, $y) = to-zero $x, $y;
$count++;
}
say "@test[] -> $count";
}
This script displays the following output:
$ raku ./total-zero.raku
5 4 -> 5
4 6 -> 3
2 5 -> 4
3 1 -> 3
7 4 -> 5
9 1 -> 9
Total Zero in Perl
This a port to Perl of the Raku program above.
use strict;
use warnings;
use feature qw/say/;
sub to_zero {
my ($x, $y) = @_;
return $x >= $y ? ($x - $y, $y) : ($x, $y - $x);
}
for my $test ([5, 4], [4, 6], [2, 5], [3, 1], [7, 4], [9, 1]) {
my ($x, $y) = @$test;
my $count = 0;
while ($x and $y ) {
($x, $y) = to_zero $x, $y;
$count++;
}
say "@$test -> $count";
}
This script displays the following output:
$ perl ./total-zero.pl
5 4 -> 5
4 6 -> 3
2 5 -> 4
3 1 -> 3
7 4 -> 5
9 1 -> 9
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 November 6, 2022. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment