Perl Weekly Challenge 263: Merge Items
These are some answers to the Week 263, 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 April 7, 2024 at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.
Task 2: Merge Items
You are given two 2-D array of positive integers, $items1
and $items2
where element is pair of (item_id, item_quantity).
Write a script to return the merged items.
Example 1
Input: $items1 = [ [1,1], [2,1], [3,2] ]
$items2 = [ [2,2], [1,3] ]
Output: [ [1,4], [2,3], [3,2] ]
Item id (1) appears 2 times: [1,1] and [1,3]. Merged item now (1,4)
Item id (2) appears 2 times: [2,1] and [2,2]. Merged item now (2,3)
Item id (3) appears 1 time: [3,2]
Example 2
Input: $items1 = [ [1,2], [2,3], [1,3], [3,2] ]
$items2 = [ [3,1], [1,3] ]
Output: [ [1,8], [2,3], [3,3] ]
Example 3
Input: $items1 = [ [1,1], [2,2], [3,3] ]
$items2 = [ [2,3], [2,4] ]
Output: [ [1,1], [2,9], [3,3] ]
Merge Items in Raku
We iterate over the items of the two arrays and store in a hash (%total
) the quantities. At the end, we reorganize the hash into two 2-D arrays of positive integers (to retrieve the input data format).
sub merge-items (@in1, @in2) {
my %total;
for (|@in1, |@in2) -> @items {
%total{@items[0]} += @items[1];
}
return map { ($_, %total{$_} ) }, %total.keys.sort;
}
my @tests = ( ((1,1), (2,1), (3,2)), ((2,2), (1,3)) ),
( ((1,2), (2,3), (1,3), (3,2)), ((3,1), (1,3)) ),
( ((1,1), (2,2), (3,3)), ((2,3), (2,4)) );
for @tests -> @test {
printf "%-15s - %-10s => ", "@test[0]", "@test[1]";
say merge-items @test[0], @test[1];
}
This program displays the following output:
$ raku ./merge-items.raku
1 1 2 1 3 2 - 2 2 1 3 => ((1 4) (2 3) (3 2))
1 2 2 3 1 3 3 2 - 3 1 1 3 => ((1 8) (2 3) (3 3))
1 1 2 2 3 3 - 2 3 2 4 => ((1 1) (2 9) (3 3))
Merge Items in Perl
This is a port to Perl of the above Raku program.
sub merge_items {
my %total;
for my $in (@_) {
for my $items (@$in) {
$total{$items->[0]} += $items->[1];
}
}
return map { "[ $_ $total{$_} ] " } sort keys %total;
}
my @tests = ( [ [[1,1], [2,1], [3,2]], [[2,2], [1,3]] ],
[ [[1,2], [2,3], [1,3], [3,2]], [[3,1], [1,3]] ],
[ [[1,1], [2,2], [3,3]], [[2,3], [2,4]] ] );
for my $test (@tests) {
printf "%-3s %-3s => ", "[$test->[0][0][0]", "$test->[0][0][1]] ...";
say merge_items @$test[0], @$test[1];
}
Note that, when printing the input test data, the program displays only the first item (the first pair) of each test.
This program displays the following output:
$ perl ./merge-items.pl
[1 1] ... => [ 1 4 ] [ 2 3 ] [ 3 2 ]
[1 2] ... => [ 1 8 ] [ 2 3 ] [ 3 3 ]
[1 1] ... => [ 1 1 ] [ 2 9 ] [ 3 3 ]
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 April 14, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment