Peter
Peter Campbell Smith

Find the target and
merge the inventory

Weekly challenge 263 — 1 April 2024

Week 263 - 1 Apr 2024

Task 2

Task — 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.

Examples


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] ]

Analysis

This is the standard stocktaking requirement that has probably been coded thousands of times since computers were invented. I first did it - in Pascal - around 50 years ago for an oil-blending company that needed to know how much it had of various raw materials and products which were stored in several locations.

The solution is in essence:

$quantity{$item->[0]} += $item->[1];

where $item[0] is the item identifier - often known in business as SKU - and $item[1] is the quantity held, which may be simply a count (say boxes of cereal) or a quantity in a known unit, eg litres or kilograms of oil.

It's easy with today's computers, but 50 years ago we could barely hold the stocklist in main memory, and the stock holdings - @items1 etc - came in on bulky magnetic tapes. In the days before PCs and the internet I flew from London to Switzerland every two weeks with the latest release of the software on a 50cm diameter hard disk which held the massive amount of 5 Mbytes of data.

Those were the days ...

Try it 

Try running the script with any input:



example: [1,2],[3,4],[4,5]



example: [3,5],[5,6],[1,7]

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2024-04-01
use utf8;     # Week 263 - task 2 - Merge items
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

my (@items1, @items2, $j);

merge_items([[1, 1], [2, 1], [3, 2]], [[2, 2], [1, 3]]);
merge_items([[1, 2], [2, 3], [1, 3], [3, 2]], [[3, 1], [1, 3]]);
merge_items([[1, 1], [2, 2], [3, 3] ], [[2,3], [2, 4]]);

# larger example
for $j (0 .. 30) {
    push @items1, [int(rand(6)) + 1, int(rand(20)) + 1];
    push @items2, [int(rand(6)) + 1, int(rand(20)) + 1];
}

merge_items(\@items1, \@items2);

sub merge_items {
    
    my (@items, $j, $item, %quantity, @input, $output);
    
    # combine inventories
    @items = @_;
    for $j (0 .. 1) {
        for $item (@{$items[$j]}) {
            $quantity{$item->[0]} += $item->[1];
            $input[$j] .= qq{[$item->[0], $item->[1]], };
        }
    }
    
    # format output 
    $output .= qq{[$_, $quantity{$_}], } for (sort keys %quantity);
    say qq[\nInput:  \@items1 = ]  . substr($input[0], 0, -2) . qq[, \@items2 = ] . substr($input[1], 0, -2);
    say qq[Output: ] . substr($output, 0, -2);
}

Output

Input:  @items1 = [1, 1], [2, 1], [3, 2], 
        @items2 = [2, 2], [1, 3]
Output: [1, 4], [2, 3], [3, 2]

Input:  @items1 = [1, 2], [2, 3], [1, 3], [3, 2], 
        @items2 = [3, 1], [1, 3]
Output: [1, 8], [2, 3], [3, 3]

Input:  @items1 = [1, 1], [2, 2], [3, 3], 
        @items2 = [2, 3], [2, 4]
Output: [1, 1], [2, 9], [3, 3]

Input:  @items1 = [6, 11], [1, 2], [6, 11], [1, 8],
[4, 15], [4, 16], [5, 6], [4, 16], [4, 5], [4, 16],
[6, 17], [4, 8], [4, 14], [1, 14], [4, 17], [4, 16],
[5, 19], [1, 12], [3, 9], [2, 7], [4, 1], [4, 9], [1, 5],
[4, 8], [1, 14], [2, 9], [3, 1], [5, 8], [6, 8], [4, 9],
[4, 4], 
        @items2 = [2, 19], [5, 20], [5, 13], [5, 16],
[6, 17], [3, 16], [4, 9], [2, 15], [5, 4], [4, 18],
[3, 13], [5, 15], [3, 13], [6, 3], [1, 18], [2, 5],
[1, 17], [6, 14], [5, 5], [4, 18], [1, 8], [4, 12],
[1, 20], [2, 8], [1, 8], [1, 6], [6, 5], [6, 20], [2, 19],
[2, 14], [6, 9]
Output: [1, 132], [2, 96], [3, 52], [4, 211], [5, 106],
[6, 115]