# Perl Weekly Challenge 234.

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

``````Submitted by: Mohammad S Anwar
You are given an array of words made up of alphabetic characters only.

Write a script to return all alphabetic characters that show up in all
words including duplicates.

Example 1
Input: @words = ("java", "javascript", "julia")
Output: ("j", "a")
Example 2
Input: @words = ("bella", "label", "roller")
Output: ("e", "l", "l")
Example 3
Input: @words = ("cool", "lock", "cook")
Output: ("c", "o")
``````

A solution may be found by preparing an array that stores for each word how many times each letter appears. Then, for each letter I can choose the minimum number of times it appears, and if positive, that is the number of times it should appear in the output. This yields a two liner.

Example 1:

``````perl -MList::Util=min -E 'for(@ARGV){my %l; \$l{\$_}++ for split ""; push @c, \%l;}
say "@ARGV -> ", join " ", map {\$l=\$_; (\$l) x min map {\$c[\$_]{\$l}} 0..@c-1} keys %{\$c[0]}
' java javascript julia
``````

Results:

``````java javascript julia -> j a
``````

Example 2:

``````perl -MList::Util=min -E 'for(@ARGV){my %l; \$l{\$_}++ for split ""; push @c, \%l;}
say "@ARGV -> ", join " ", map {\$l=\$_; (\$l) x min map {\$c[\$_]{\$l}} 0..@c-1} keys %{\$c[0]}
' bella label roller
``````

Results:

``````bella label roller -> e l l
``````

Example 3:

``````perl -MList::Util=min -E 'for(@ARGV){my %l; \$l{\$_}++ for split ""; push @c, \%l;}
say "@ARGV -> ", join " ", map {\$l=\$_; (\$l) x min map {\$c[\$_]{\$l}} 0..@c-1} keys %{\$c[0]}
' cool lock cook
``````

Results:

``````cool lock cook -> c o
``````

The corresponding full code is:

`````` 1  # Perl weekly challenge 234
2  # Task 1:  Common Characters
3  #
5  use v5.36;
6  use List::Util qw(min);
7  die <<~"FIN" unless @ARGV;
8      Usage: \$0 W1 [W2...]
9      to find the common characters in all words W1, W2...
10      FIN
11  my @letters_of_word;
12  for(@ARGV){
13      my %count_of_letter;
14      \$count_of_letter{\$_}++ for split "";
15      push @letters_of_word, \%count_of_letter;
16  }
17  my \$number_of_words=@letters_of_word;
18  my @result=map {
19      my \$letter=\$_;
20      my \$repetition=min map {
21  	my \$word_number=\$_;
22  	\$letters_of_word[\$word_number]{\$letter}//0
23      } 0..\$number_of_words-1;
24      (\$letter) x \$repetition;
25  } keys %{\$letters_of_word[0]};
26  say "@ARGV -> @result";
``````

Examples:

``````./ch-1.pl java javascript julia
./ch-1.pl bella label roller
./ch-1.pl cool lock cook
``````

Results:

``````java javascript julia -> j a
bella label roller -> l l e
cool lock cook -> o c
``````

``````Submitted by: Mohammad S Anwar
You are given an array of positive integers.

Write a script to find the number of triplets (i, j, k) that satisfies
num[i] != num[j], num[j] != num[k] and num[k] != num[i].

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

(0, 2, 4) because 4 != 2 != 3
(1, 2, 4) because 4 != 2 != 3
(2, 3, 4) because 2 != 4 != 3
Example 2
Input: @ints = (1, 1, 1, 1, 1)
Ouput: 0
Example 3
Input: @ints = (4, 7, 1, 10, 7, 4, 1, 1)
Output: 28

triplets of 1, 4, 7  = 3x2×2 = 12 combinations
triplets of 1, 4, 10 = 3×2×1 = 6  combinations
triplets of 4, 7, 10 = 2×2×1 = 4  combinations
triplets of 1, 7, 10 = 3x2x1 = 6 combinations
``````

The last example gives a good hint for a solution. First, map each number to the number of times it appears. Then, for each combination of three distinct numbers, multiply the corresponding repetitions. Using `sum0` and `product` from `List::Util` and `combinations` from `Algorithm::Combinatorics` this yields a one liner.

Example 1:

``````perl -MAlgorithm::Combinatorics=combinations -MList::Util=sum0,product -E '
++\$c{\$_} for @ARGV; @n=keys %c; say "@ARGV -> ", @n<3?0:sum0 map {product @c{@\$_}} combinations(\@n,3);
' 4 4 2 4 3
``````

Results:

``````4 4 2 4 3 -> 3
``````

Example 2:

``````perl -MAlgorithm::Combinatorics=combinations -MList::Util=sum0,product -E '
++\$c{\$_} for @ARGV; @n=keys %c; say "@ARGV -> ", @n<3?0:sum0 map {product @c{@\$_}} combinations(\@n,3);
' 1 1 1 1 1
``````

Results:

``````1 1 1 1 1 -> 0
``````

Example 3:

``````perl -MAlgorithm::Combinatorics=combinations -MList::Util=sum0,product -E '
++\$c{\$_} for @ARGV; @n=keys %c; say "@ARGV -> ", @n<3?0:sum0 map {product @c{@\$_}} combinations(\@n,3);
' 4 7 1 10 7 4 1 1
``````

Results:

``````4 7 1 10 7 4 1 1 -> 28
``````

The corresponding full code is:

`````` 1  # Perl weekly challenge 234
2  # Task 2:  Unequal Triplets
3  #
5  use v5.36;
6  use Algorithm::Combinatorics qw(combinations);
7  use List::Util qw(sum0 product);
8  die <<~"FIN" unless @ARGV;
9      Usage: \$0 N1 [N2...]
10      to count the number of unequal triplets in the set {N1 N2...}
11      FIN
12  my %count_for_number;
13  ++\$count_for_number{\$_} for @ARGV;
14  my @numbers=keys %count_for_number;
15  my \$result=@numbers<3
16      ? 0
17      : sum0 map {
18  	product @count_for_number{@\$_}
19  } combinations(\@numbers,3);
20  say "@ARGV -> \$result",
``````

Examples:

``````./ch-2.pl 4 4 2 4 3
./ch-2.pl 1 1 1 1 1
./ch-2.pl 4 7 1 10 7 4 1 1
``````

Results:

``````4 4 2 4 3 -> 3
1 1 1 1 1 -> 0
4 7 1 10 7 4 1 1 -> 28
``````
Written on September 11, 2023