Perl Weekly Challenge 277.

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

Task 1: Count Common

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

Write a script to return the count of words that appears in both arrays exactly once.

Example 1
Input: @words1 = ("Perl", "is", "my", "friend")
       @words2 = ("Perl", "and", "Raku", "are", "friend")
Output: 2

The words "Perl" and "friend" appear once in each array.
Example 2
Input: @words1 = ("Perl", "and", "Python", "are", "very", "similar")
       @words2 = ("Python", "is", "top", "in", "guest", "languages")
Output: 1
Example 3
Input: @words1 = ("Perl", "is", "imperative", "Lisp", "is", "functional")
       @words2 = ("Crystal", "is", "similar", "to", "Ruby")
Output: 0

I can keep two hashes with counts for each word in each array. Then I can grep the keys of any of these hashes by their count in both arrays. I assume the inputs are in space separated strings in @ARGV. The results fits a 1.5liner.

Example 1:

perl -E '
for(@ARGV){$c[$i]{lc$_}++ for split " ", $_;$i++} say((map {"[$_]"} @ARGV), "->",
0+grep{$c[0]{$_}==$c[1]{$_}==1}keys %{$c[0]})
' "Perl is my friend" "Perl and Raku are friend"

Results:

[Perl is my friend][Perl and Raku are friend]->2

Example 2

perl -E '
for(@ARGV){$c[$i]{lc$_}++ for split " ", $_;$i++} say((map {"[$_]"} @ARGV), "->",
0+grep{$c[0]{$_}==$c[1]{$_}==1}keys %{$c[0]})
' "Perl and Python are very similar" "Python is top in guest languages"

Results:

[Perl and Python are very similar][Python is top in guest languages]->1

perl -E '
for(@ARGV){$c[$i]{lc$_}++ for split " ", $_;$i++} say 0+grep{$c[0]{$_}==$c[1]{$_}==1}keys %{$c[0]}
' "Perl is imperative Lisp is functional" "Crystal is similar to Ruby"

Results:

0

The full code is similar. I use for_list to deal with more than one example at a time.

 1  # Perl weekly challenge 277
 2  # Task 1:  Count Common
 3  #
 4  # See https://wlmb.github.io/2024/07/08/PWC277/#task-1-count-common
 5  use v5.36;
 6  use experimental qw(for_list);
 7  die <<~"FIN" unless @ARGV and @ARGV%2==0;
 8      Usage: $0 S11 S12 [S21 S22...]
 9      to count pair of words that appear once in the space separated
10      strings Sn1 and Sn2.
11      FIN
12  for my ($s1, $s2)(@ARGV){
13      my @strings=($s1, $s2);
14      my @counts;
15      my $i=0;
16      for(@strings){
17          $counts[$i]{lc $_}++ for split " ", $_;
18          $i++;
19      }
20      say((map{"words$_ = [$strings[$_]] "}(0,1)), " -> ",
21          0+grep{$counts[0]{$_}==$counts[1]{$_}==1}keys %{$counts[0]});
22  }

Example:

./ch-1.pl "Perl is my friend" "Perl and Raku are friend" \
          "Perl and Python are very similar" "Python is top in guest languages" \
          "Perl is imperative Lisp is functional" "Crystal is similar to Ruby"

Results:

words0 = [Perl is my friend] words1 = [Perl and Raku are friend]  -> 2
words0 = [Perl and Python are very similar] words1 = [Python is top in guest languages]  -> 1
words0 = [Perl is imperative Lisp is functional] words1 = [Crystal is similar to Ruby]  -> 0

Task 2: Strong Pair

Submitted by: Mohammad Sajid Anwar
You are given an array of integers, @ints.

Write a script to return the count of all strong pairs in the given array.

A pair of integers x and y is called strong pair if it satisfies:
0 < |x - y| < min(x, y).

Example 1
Input: @ints = (1, 2, 3, 4, 5)
Ouput: 4

Strong Pairs: (2, 3), (3, 4), (3, 5), (4, 5)
Example 2
Input: @ints = (5, 7, 1, 7)
Ouput: 1

Strong Pairs: (5, 7)

One solution is to generate all pairs and test their strength. The second example shows I have to get rid of repetitions first.

perl -MAlgorithm::Combinatorics=combinations -MList::Util=min,uniqnum -E '
@u=uniqnum(@ARGV); say "@ARGV -> ", 0+grep {0<abs($_->[1]-$_->[0])<min(@$_)}combinations(\@u,2)
' 1 2 3 4 5

Results:

1 2 3 4 5 -> 4

Results:

1 2 3 4 5 -> 4

perl -MAlgorithm::Combinatorics=combinations -MList::Util=min,uniqnum -E '
@u=uniqnum(@ARGV); say "@ARGV -> ", 0+grep {0<abs($_->[1]-$_->[0])<min(@$_)}combinations(\@u,2)
' 5 7 1 7

Results:

5 7 1 7 -> 1

The full code is:

 1  # Perl weekly challenge 277
 2  # Task 2:  Strong Pair
 3  #
 4  # See https://wlmb.github.io/2024/07/08/PWC277/#task-2-strong-pair
 5  use v5.36;
 6  use Algorithm::Combinatorics qw(combinations);
 7  use List::Util qw(min uniqnum);
 8  die <<~"FIN" unless @ARGV;
 9      Usage: $0 N1 N2...
10      to count the number of strong pairs of numbers N1 N2...
11      FIN
12  my @uniq=uniqnum(@ARGV);
13  say "@ARGV -> ", 0+grep {0<abs($_->[1]-$_->[0])<min(@$_)}combinations(\@uniq,2);

Examples:

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

Results:

1 2 3 4 5 -> 4
5 7 1 7 -> 1
Written on July 8, 2024