Perl Weekly Challenge 225: Left Right Sum Diff
These are some answers to the Week 225, 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 July 16, 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: Left Right Sum Diff
You are given an array of integers, @ints
.
Write a script to return left right sum diff array as shown below:
@ints = (a, b, c, d, e)
@left = (0, a, (a+b), (a+b+c))
@right = ((c+d+e), (d+e), e, 0)
@left_right_sum_diff = ( | 0 - (c+d+e) |,
| a - (d+e) |,
| (a+b) - e |,
| (a+b+c) - 0 | )
Example 1:
Input: @ints = (10, 4, 8, 3)
Output: (15, 1, 11, 22)
@left = (0, 10, 14, 22)
@right = (15, 11, 3, 0)
@left_right_sum_diff = ( |0-15|, |10-11|, |14-3|, |22-0|)
= (15, 1, 11, 22)
Example 2:
Input: @ints = (1)
Output: (0)
@left = (0)
@right = (0)
@left_right_sum_diff = ( |0-0| ) = (0)
Example 3:
Input: @ints = (1, 2, 3, 4, 5)
Output: (14, 11, 6, 1, 10)
@left = (0, 1, 3, 6, 10)
@right = (14, 12, 9, 5, 0)
@left_right_sum_diff = ( |0-14|, |1-12|, |3-9|, |6-5|, |10-0|)
= (14, 11, 6, 1, 10)
Frankly, I don't understand the logic of this task, nor its aim. So I'll simply mimic blindly the task description and examples. The unstated assumption derived from the examples is that the left and right arrays should have the same size as the input array, that the left array should have a zero followed by partial sums of the input array except the last one, and that the right array should also have partial sums of the input array in reverse order, except the first one, and followed by a zero.
Left Right Sum Diff in Raku
In Raku, we can use reduction operator [] together with the +
operator (to sum the items), prefixed with a \
to obtain partial or intermediate sums:
say [\+] 1..5; # prints: (1 3 6 10 15)
This is sometimes called a triangular reduction. We use it for computing both the left and the right arrays. The rest of the program is straight forward: we use a map
to perform the subtractions.
sub lrsd (@in) {
my @l = (0, [\+] @in[0..@in.end - 1]).flat;
my @r =
(( [\+] @in.reverse[0..@in.end - 1]).reverse, 0).flat;
return map { (@l[$_] - @r[$_]).abs }, 0..@l.end;
}
my @tests = (10, 4, 8, 3), (1,), (1, 2, 3, 4, 5);
for @tests -> @test {
printf "%-10s => ", "@test[]";
say lrsd @test;
}
This program displays the following output:
$ raku ./left-right-sum-diff.raku
10 4 8 3 => (15 1 11 22)
1 => (0)
1 2 3 4 5 => (14 11 6 1 10)
Left Right Sum Diff in Perl
Perl doesn't have the reduction operator, but it is not complicated to compute partial sums in a for
loop.
use strict;
use warnings;
use feature 'say';
sub lrsd {
my @in = @_;
my @l = (0);
push @l, $l[-1] + $in[$_] for 0..$#in-1;
my @r = (0);
push @r, $r[-1] + $in[$_] for reverse 1..$#in;
@r = reverse @r;
return join " ", map { abs ($l[$_] - $r[$_]) } 0..$#l;
}
my @tests = ([10, 4, 8, 3], [1,], [1, 2, 3, 4, 5] );
for my $test (@tests) {
printf "%-10s => ", "@$test";
say lrsd @$test;
}
This program displays the following output:
$ perl ./left-right-sum-diff.pl
10 4 8 3 => 15 1 11 22
1 => 0
1 2 3 4 5 => 14 11 6 1 10
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 July 23, 2023. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment