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
/;