Perl Weekly Challenge 263.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 263.
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 $k[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
The task seems straightforward: sort the entries and filter the indices. I assume the arguments are in @ARGV starting with k.
Example 1:
perl -E '
$k=shift; @x=sort{$a<=>$b}@ARGV; say "k=$k, ints=(@ARGV) -> ", join " ", "(", grep({$x[$_]==$k} (0..@x-1)), ")";
' 2 1 5 3 2 4 2
Results:
k=2, ints=(1 5 3 2 4 2) -> ( 1 2 )
Example 2:
perl -E '
$k=shift; @x=sort{$a<=>$b}@ARGV; say "k=$k, ints=(@ARGV) -> ", join " ", "(", grep({$x[$_]==$k} (0..@x-1)), ")";
' 6 1 2 4 3 5
Results:
k=6, ints=(1 2 4 3 5) -> ( )
Example 3:
perl -E '
$k=shift; @x=sort{$a<=>$b}@ARGV; say "k=$k, ints=(@ARGV) -> ", join " ", "(", grep({$x[$_]==$k} (0..@x-1)), ")";
' 4 5 3 2 4 2 1
Results:
k=4, ints=(5 3 2 4 2 1) -> ( 4 )
The full code follows:
1 # Perl weekly challenge 263
2 # Task 1: Target Index
3 #
4 # See https://wlmb.github.io/2024/04/01/PWC263/#task-1-target-index
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 k N0 [N1...]
8 to find the indices of the array N0 N1... (after sorting) for which
9 N_i=k
10 FIN
11 my $k=shift;
12 my @sorted=sort{$a<=>$b}@ARGV;
13 say "k=$k, ints=(@ARGV) -> ",
14 join " ", "(", grep({$sorted[$_]==$k} (0..@sorted-1)), ")";
Example:
for i in "2 1 5 3 2 4 2" "6 1 2 4 3 5" "4 5 3 2 4 2 1";do ./ch-1.pl `echo $i`; done
Results:
k=2, ints=(1 5 3 2 4 2) -> ( 1 2 )
k=6, ints=(1 2 4 3 5) -> ( )
k=4, ints=(5 3 2 4 2 1) -> ( 4 )
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] ]
As items to be merged may be part of the same list, it seems
unnecesary to keep them in two lists. I use PDL to easily convert
between several nested arrays to a simple list which I iterate using
the new for_list
. I accumulate values in a hash and finally, I print
key,value pairs. This fits a longish one-liner.
Example 1:
perl -Mexperimental=for_list -MPDL -E '
push @e, pdl($_)->list for @ARGV;for my($x,$y)(@e){$v{$x}+=$y};@r=map {"[$_,$v{$_}]"} keys %v;say "@ARGV -> [@r]";
' "[[1,2],[2,3],[1,3],[3,2]]" "[[3,1],[1,3]]"
Results:
[[1,2],[2,3],[1,3],[3,2]] [[3,1],[1,3]] -> [[1,8] [3,3] [2,3]]
I got the expected results but unsorted.
Example 2:
perl -Mexperimental=for_list -MPDL -E '
push @e, pdl($_)->list for @ARGV;for my($x,$y)(@e){$v{$x}+=$y};@r=map {"[$_,$v{$_}]"} keys %v;say "@ARGV -> [@r]";
' "[[1,2],[2,3],[1,3],[3,2]]" "[[3,1],[1,3]]"
Results:
[[1,2],[2,3],[1,3],[3,2]] [[3,1],[1,3]] -> [[2,3] [3,3] [1,8]]
Example 3:
perl -Mexperimental=for_list -MPDL -E '
push @e, pdl($_)->list for @ARGV;for my($x,$y)(@e){$v{$x}+=$y};@r=map {"[$_,$v{$_}]"} keys %v;say "@ARGV -> [@r]";
' "[[1,1],[2,2],[3,3]]" "[[2,3],[2,4]]"
Results:
[[1,1],[2,2],[3,3]] [[2,3],[2,4]] -> [[1,1] [2,9] [3,3]]
The full code is similar. I just add some checks and I sort the result.
1 # Perl weekly challenge 263
2 # Task 2: Merge Items
3 #
4 # See https://wlmb.github.io/2024/04/01/PWC263/#task-2-merge-items
5 use v5.36;
6 use PDL; # use the perl data language to convert the input to a list of keys-values
7 use experimental qw(for_list); # use for list to process key-value pairs
8 die <<~"FIN" unless @ARGV;
9 Usage: $0 "[[K11,V11],[K12,V12]...]]" "[[K21,V21],[K22,V22],...]" ...
10 to accumulate all values Vij corresponding to each unique key Kn=Kij
11 FIN
12 my @keyvals;
13 push @keyvals, pdl($_)->list for @ARGV;
14 my %merged;
15 for my($key, $val)(@keyvals){
16 $merged{$key}+=$val
17 };
18 my @result = map {"[$_,$merged{$_}]"} sort {$a cmp $b} keys %merged;
19 say "@ARGV -> [@result]";
Example:
./ch-2.pl "[[1,2],[2,3],[1,3],[3,2]]" "[[3,1],[1,3]]"
./ch-2.pl "[[1,2],[2,3],[1,3],[3,2]]" "[[3,1],[1,3]]"
./ch-2.pl "[[1,1],[2,2],[3,3]]" "[[2,3],[2,4]]"
Results:
[[1,2],[2,3],[1,3],[3,2]] [[3,1],[1,3]] -> [[1,8] [2,3] [3,3]]
[[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]]
Note that I may more or less than two input arrays.
Other examples:
./ch-2.pl "[[1,2],[2,3],[1,3],[3,2]]"
./ch-2.pl "[[1,2],[2,3],[1,3],[3,2]]" "[[3,1],[1,3]]" "[[1,1],[2,2],[3,3]]" "[[2,3],[2,4]]"
Results:
[[1,2],[2,3],[1,3],[3,2]] -> [[1,5] [2,3] [3,2]]
[[1,2],[2,3],[1,3],[3,2]] [[3,1],[1,3]] [[1,1],[2,2],[3,3]] [[2,3],[2,4]] -> [[1,9] [2,12] [3,6]]