Peter’s blog ✴ Week 263 ✴ 1 April 2024

THE WEEKLY CHALLENGE
Find the target and merge the inventory

The Perl Camel

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.

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

Perl Weekly’s review

from PW issue 663

Cute and easy to follow solutions in Perl. Anybody can follow it and try it. Thanks for sharing.

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);
}

10 lines of code

Output from script

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]
	

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain