05 April 2024 | Challenge 263 |
Which Witch?
This week brings a new occasion for some PDL witchery.
Task 1: Target Index
Submitted by: Mohammad Sajid Anwar
You are given an array of integers, @ints
and a target element $k
.
Write a script to return the list of indices in the sorted array where the element is same as the given target element.
Example 1
Input: @ints = (1, 5, 3, 2, 4, 2), $k = 2
Output: (1, 2)
Sorted array: (1, 2, 2, 3, 4, 5)
Target indices: (1, 2) as $ints[1] = 2 and $ints[2] = 2
Example 2
Input: @ints = (1, 2, 4, 3, 5), $k = 6
Output: ()
No element in the given array matching the given target.
Example 3
Input: @ints = (5, 3, 2, 4, 2, 1), $k = 4
Output: (4)
Sorted array: (1, 2, 2, 3, 4, 5)
Target index: (4) as $ints[4] = 4
Solution
With which
as one of PDL
’s “primitive” functions, this task can be solved as a one-liner.
use strict;
use warnings;
use PDL;
sub t_idx {
my $k = shift;
which $k == pdl(@_)->qsort;
}
See the full solution.
Task 2: Merge Items
Submitted by: Mohammad Sajid Anwar
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] ]
Solution
At first glance the given items look like sparse vectors, which is disproved by Example 2, where an index appears twice within the same list.
Nevertheless following a sparse vector approach, again utilizing the magic of PDL
.
The supplementary module PDL::CCS
provides a convenient implementation of “compressed column storage” sparse vectors, matrices etc.
- First we create a list of 2-d ndarrays from the given data.
- Next we identify all indices contained within the ndarrays.
- Then we build a sparse vector that has zero values at the previously found index positions.
- All item values are then added to their corresponding index position in the sparse vector.
- Finally we pair the indices with their value sums.
use strict;
use warnings;
use PDL;
use PDL::NiceSlice;
use PDL::CCS;
sub merge_items {
my @pdl = map pdl($_), @_;
my $which = null->glue(0, map $_((0)), @pdl)->uniq;
my $sum = PDL::CCS::Nd->newFromWhich($which->dummy(0), zeroes($which),
missing => 'BAD');
$sum->indexND($_(0)) += $_(1) for null->glue(1, @pdl)->dog;
$which->cat($sum->whichVals)->xchg(0, 1);
}
See the full solution.
If you have a question about this post or if you like to comment on it, feel free to open an issue in my github repository.