Perl Weekly Challenge 308.

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

Task 1: Count Common

Submitted by: Mohammad Sajid Anwar
You are given two array of strings, @str1 and @str2.

Write a script to return the count of common strings in both arrays.

Example 1
Input: @str1 = ("perl", "weekly", "challenge")
       @str2 = ("raku", "weekly", "challenge")
Output: 2
Example 2
Input: @str1 = ("perl", "raku", "python")
       @str2 = ("python", "java")
Output: 1
Example 3
Input: @str1 = ("guest", "contribution")
       @str2 = ("fun", "weekly", "challenge")
Output: 0

There is some ambiguity if one or the other array has repetitions. I guess the arrays should be used as sets, and therefore, in-array repetitions should be eliminated. I could use one of the many Set modules in CPAN or simply represent a set with a hash, with the elements being the keys. I assume each of the two arrays are input as a space separated string. I grep the keys of one set by membership in the other set, yielding the interesection, and count the number of surviving elements. I assume upper and lower case letters are to be taken as different. Otherwise, the words could be normalized to one or the other case. The result fits a one-liner.

Example 1:

perl -E '
@a=@ARGV;for$x(0,1){++$s[$x]{$_}for split" ",$a[$x]}say"s1=$a[0], s2=$a[1] -> ",0+grep{$s[0]{$_}}keys %{$s[1]}
' "perl weekly challenge" "raku weekly challenge"

Results:

s1=perl weekly challenge, s2=raku weekly challenge -> 2

Example 2:

perl -E '
@a=@ARGV;for$x(0,1){++$s[$x]{$_}for split" ",$a[$x]}say"s1=$a[0], s2=$a[1] -> ",0+grep{$s[0]{$_}}keys %{$s[1]}
' "perl raku python" "python java"

Results:

s1=perl raku python, s2=python java -> 1

Example 3:

perl -E '
@a=@ARGV;for$x(0,1){++$s[$x]{$_}for split" ",$a[$x]}say"s1=$a[0], s2=$a[1] -> ",0+grep{$s[0]{$_}}keys %{$s[1]}
' "guest contribution" "fun weekly challenge"

Results:

s1=guest contribution, s2=fun weekly challenge -> 0

The corresponding full code is:

 1  # Perl weekly challenge 308
 2  # Task 1:  Count Common
 3  #
 4  # See https://wlmb.github.io/2025/02/10/PWC308/#task-1-count-common
 5  use v5.36;
 6  die <<~"FIN" unless  @ARGV==2;
 7      Usage $0 S1 S2
 8      to find how many words are common to the
 9      space separated strings S1 and S2
10      FIN
11  my @seen;
12  for my $x(0,1){
13      ++$seen[$x]{$_}for split" ",$ARGV[$x];
14  }
15  say "s1 = $ARGV[0], s2=$ARGV[1] -> ", 0+grep{$seen[0]{$_}} keys %{$seen[1]};

Example:

./ch-1.pl "perl weekly challenge" "raku weekly challenge"
./ch-1.pl "perl raku python" "python java"
./ch-1.pl "guest contribution" "fun weekly challenge"

Results:

s1 = perl weekly challenge, s2=raku weekly challenge -> 2
s1 = perl raku python, s2=python java -> 1
s1 = guest contribution, s2=fun weekly challenge -> 0

Task 2: Decode XOR

Submitted by: Mohammad Sajid Anwar
You are given an encoded array and an initial integer.

Write a script to find the original array that produced the given encoded array.
It was encoded such that encoded[i] = orig[i] XOR orig[i + 1].

Example 1
Input: @encoded = (1, 2, 3), $initial = 1
Output: (1, 0, 2, 1)

Encoded array created like below, if the original array was (1, 0, 2, 1)
$encoded[0] = (1 xor 0) = 1
$encoded[1] = (0 xor 2) = 2
$encoded[2] = (2 xor 1) = 3
Example 2
Input: @encoded = (6, 2, 7, 3), $initial = 4
Output: (4, 2, 0, 7, 4)

The problem is easily solved by noticing that x^(x^y) yields y, as shown by the following truth table,

x y x ^ y x ^ (x ^ y)
0 0 0 ^ 0 → 0 0 ^ 0 → 0
0 1 0 ^ 1 → 1 0 ^ 1 → 1
1 0 1 ^ 0 → 1 1 ^ 1 → 0
1 1 1 ^ 1 → 0 1 ^ 0 → 1

where I denote XOR with the Perl operator ^. Thus, I can solve the problem iteratively: from encoded[n]=orig[n]^orig[n+1] I solve orig[n+1]=orig[n]^encoded[n]. I start the iteration from orig[0]=initial. This yields a one liner.

Example 1:

perl -E '
@a=@ARGV; push @o,shift; push @o,$o[-1]^$_ for @ARGV; say "initial=$a[0], encoded=@ARGV -> @o"
' 1 1 2 3

Results:

initial=1, encoded=1 2 3 -> 1 0 2 1

Example 2:

perl -E '
@a=@ARGV; push @o,shift; push @o,$o[-1]^$_ for @ARGV; say "initial=$a[0], encoded=@ARGV -> @o"
' 4 6 2 7 3

Results:

initial=4, encoded=6 2 7 3 -> 4 2 0 7 4

The full code is:

 1  # Perl weekly challenge 308
 2  # Task 2:  Decode XOR
 3  #
 4  # See https://wlmb.github.io/2025/02/10/PWC308/#task-2-decode-xor
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV;
 7      Usage: $0 I E_0 E_1...E_n
 8      to decode the sequence  E_j=Oj^O_{j+1} and find the original sequence
 9      O_j, j=0..n+1 given its starting value I
10      FIN
11  push my @original, my $initial=shift;
12  push @original, $original[-1]^$_ for @ARGV;
13  say "initial=$initial, encoded=@ARGV -> @original"

Example:

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

Results:

initial=1, encoded=1 2 3 -> 1 0 2 1
initial=4, encoded=6 2 7 3 -> 4 2 0 7 4

/;

Written on February 10, 2025