## 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.

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.