Perl Weekly Challenge 242.

My solutions (task 1 and task 2 ) to the The Weekly Challenge - 242.

Task 1: Missing Members

Submitted by: Mohammad S Anwar
You are given two arrays of integers.

Write a script to find out the missing members in each other arrays.

Example 1
Input: @arr1 = (1, 2, 3)
       @arr2 = (2, 4, 6)
Output: ([1, 3], [4, 6])

(1, 2, 3) has 2 members (1, 3) missing in the array (2, 4, 6).
(2, 4, 6) has 2 members (4, 6) missing in the array (1, 2, 3).
Example 2
Input: @arr1 = (1, 2, 3, 3)
       @arr2 = (1, 1, 2, 2)
Output: ([3])

(1, 2, 3, 3) has 2 members (3, 3) missing in the array (1, 1, 2, 2).
Since they are same, keep just one.
(1, 1, 2, 2) has 0 member missing in the array (1, 2, 3, 3).

I use a hash of bitmasks to record whether an element is only in the first array (1), only in the second array (2), or in both (3). Then I test all the keys and output the missing elements, corresponding to the bitmasks 1 or 2. This fits a two-liner.

Example 1:

perl -E '
@a=@ARGV; for(0,1){$b=2**$_; $x{$_}|=$b for split " ", $a[$_]} for(0,1){$b=2**$_;
@{$r[$_]}=grep{$x{$_}==$b}keys %x} say "[$a[0]],[$a[1]] -> [@{$r[0]}], [@{$r[1]}]";
' "1 2 3" "2 4 6"

Results:

[1 2 3],[2 4 6] -> [3 1], [4 6]

Example 2:

perl -E '
@a=@ARGV; for(0,1){$b=2**$_; $x{$_}|=$b for split " ", $a[$_]} for(0,1){$b=2**$_;
@{$r[$_]}=grep{$x{$_}==$b}keys %x} say "[$a[0]],[$a[1]] -> [@{$r[0]}], [@{$r[1]}]";
' "1 1 2 2" "1 2 3 3"

Results:

[1 1 2 2],[1 2 3 3] -> [], [3]

Notice that I did print empty results. This is simpler and allows distinguishing the case where the first array has no missing elements from that where it is the second array that has no missing members.

Example 2 permutted:

perl -E '
@a=@ARGV; for(0,1){$b=2**$_; $x{$_}|=$b for split " ", $a[$_]} for(0,1){$b=2**$_;
@{$r[$_]}=grep{$x{$_}==$b}keys %x} say "[$a[0]],[$a[1]] -> [@{$r[0]}], [@{$r[1]}]";
' "1 1 2 2" "1 2 3 3"

Results:

[1 1 2 2],[1 2 3 3] -> [], [3]

The full code is similar.

 1  # Perl weekly challenge 242
 2  # Task 1:  Missing Members
 3  #
 4  # See https://wlmb.github.io/2023/11/06/PWC242/#task-1-missing-members
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV==2;
 7      Usage: $0 S0 S1
 8      to find the space-separated elements of S0 missing from S1 and viceversa.
 9      FIN
10  my @bits=(1,2);
11  my %bitmasks;
12  for(0,1){
13      my $bit=$bits[$_];
14      $bitmasks{$_}|=$bit for split " ", $ARGV[$_];
15  }
16  my @results;
17  for(0,1){
18      my $bit=$bits[$_];
19      @{$results[$_]}=sort {$a <=> $b} grep{$bitmasks{$_}==$bit}keys %bitmasks;
20  }
21  say "[$ARGV[0]],[$ARGV[1]] -> [@{$results[0]}], [@{$results[1]}]";

Examples:

./ch-1.pl "1 2 3" "2 4 6"
./ch-1.pl "1 2 3 3" "1 1 2 2"
./ch-1.pl "1 1 2 2" "1 2 3 3"

Results:

[1 2 3],[2 4 6] -> [1 3], [4 6]
[1 2 3 3],[1 1 2 2] -> [3], []
[1 1 2 2],[1 2 3 3] -> [], [3]

Task 2: Flip Matrix

Submitted by: Mohammad S Anwar
You are given n x n binary matrix.

Write a script to flip the given matrix as below.


1 1 0
0 1 1
0 0 1

a. Reverse each row

0 1 1
1 1 0
1 0 0

b. Invert each member

1 0 0
0 0 1
0 1 1

Example 1
Input: @matrix = ([1, 1, 0], [1, 0, 1], [0, 0, 0])
Output: ([1, 0, 0], [0, 1, 0], [1, 1, 1])
Example 2
Input: @matrix = ([1, 1, 0, 0], [1, 0, 0, 1], [0, 1, 1, 1], [1, 0, 1, 0])
Output: ([1, 1, 0, 0], [0, 1, 1, 0], [0, 0, 0, 1], [1, 0, 1, 0])

I use the Perl Data Language PDL to solve this problem, as it has operators to reverse and invert rows of matrices. I assume the input is given by a string in @ARGV. This yields a half-liner.

Examples:

perl -MPDL -E 'for(@ARGV){$x=pdl($_); say "Input${x}Output", !$x->slice([-1,0])}
' "[[1,1,0],[1,0,1],[0,0,0]]" "[[1,1,0,0], [1,0,0,1], [0,1,1,1], [1,0,1,0]]"

Results:

Input
[
 [1 1 0]
 [1 0 1]
 [0 0 0]
]
Output
[
 [1 0 0]
 [0 1 0]
 [1 1 1]
]

Input
[
 [1 1 0 0]
 [1 0 0 1]
 [0 1 1 1]
 [1 0 1 0]
]
Output
[
 [1 1 0 0]
 [0 1 1 0]
 [0 0 0 1]
 [1 0 1 0]
]

The full code is similar:

 1  # Perl weekly challenge 242
 2  # Task 2:  Flip Matrix
 3  #
 4  # See https://wlmb.github.io/2023/11/06/PWC242/#task-2-flip-matrix
 5  use v5.36;
 6  use PDL;
 7  die <<~"FIN" unless @ARGV;
 8      Usage: $0 M0 [M1...]
 9      to reverse the rows and invert the elements of the matrices M0 M1...
10      provided as strings like "[[m00 m01...],[m10 m11...]...]"
11      FIN
12  for(@ARGV){
13      my $x=pdl($_);
14      say "Input${x}Output", !$x->slice([-1,0]);
15  }
16  

Examples:

./ch-2.pl "[[1,1,0],[1,0,1],[0,0,0]]" "[[1,1,0,0], [1,0,0,1], [0,1,1,1], [1,0,1,0]]"

Results:

Input
[
 [1 1 0]
 [1 0 1]
 [0 0 0]
]
Output
[
 [1 0 0]
 [0 1 0]
 [1 1 1]
]

Input
[
 [1 1 0 0]
 [1 0 0 1]
 [0 1 1 1]
 [1 0 1 0]
]
Output
[
 [1 1 0 0]
 [0 1 1 0]
 [0 0 0 1]
 [1 0 1 0]
]
Written on November 6, 2023