Find the target and
merge the inventory
Weekly challenge 263 — 1 April 2024
Week 263: 1 Apr 2024
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] ]
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 ...
#!/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); }
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