Perl Weekly Challenge 255.

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

Task 1: Odd Character

Submitted by: Mohammad Sajid Anwar
You are given two strings, $s and $t. The string $t is generated
using the shuffled characters of the string $s with an additional character.

Write a script to find the additional character in the string $t..

Example 1
Input: $s = "Perl" $t = "Preel"
Output: "e"
Example 2
Input: $s = "Weekly" $t = "Weeakly"
Output: "a"
Example 3
Input: $s = "Box" $t = "Boxy"
Output: "y"

I can count each character using a hash, up for the string $t and down for the string $s, and look for the odd character with a count of -1. I simplify the code by deleting the entries with a count of 0, so I get all odd characters, in case there are more than one. This fits a oneliner:

Example 1:

perl -E '
($t,$s)=@ARGV; ++$c{$_} for split "", fc $t; --$c{$_}||delete $c{$_} for split "", fc $s; say "$t, $s -> ", keys %c;
' Perl Preel

Results:

Perl, Preel -> e

Example 2:

perl -E '
($t,$s)=@ARGV; ++$c{$_} for split "", fc $t; --$c{$_}||delete $c{$_} for split "", fc $s; say "$t, $s -> ", keys %c;
' Weekly Weeakly

Results:

Weekly, Weeakly -> a

Example 3:

perl -E '
($t,$s)=@ARGV; ++$c{$_} for split "", fc $t; --$c{$_}||delete $c{$_} for split "", fc $s; say "$t, $s -> ", keys %c;
' Box Boxy

Results:

Box, Boxy -> y

For the full code I use for_list and add some tests:

 1  # Perl weekly challenge 255
 2  # Task 1:  Odd Character
 3  #
 4  # See https://wlmb.github.io/2024/02/05/PWC255/#task-1-odd-character
 5  use v5.36;
 6  use experimental qw(for_list);
 7  die <<~"FIN" unless @ARGV && @ARGV%2==0;
 8      Usage: $0 S0 T0 [S1 T1...]
 9      to find the odd characters in the string pairs Sn Tn
10      FIN
11  for my ($s,$t)(@ARGV){
12      warn "Length should differ by one" unless length $t == 1+length $s;
13      my %count;
14      ++$count{$_} for split "", fc $s;
15      --$count{$_}||delete $count{$_} for split "", fc $t;
16      warn "More than one odd character" unless (keys %count)==1;
17      say "$t, $s -> ", keys %count;
18  }

Examples:

./ch-1.pl Perl Preel Weekly Weeakly Box Boxy

Results:

Perl, Preel -> e
Weekly, Weeakly -> a
Box, Boxy -> y

Task 2: Most Frequent Word

Submitted by: Mohammad Sajid Anwar
You are given a paragraph $p and a banned word $w.

Write a script to return the most frequent word that is not banned.

Example 1
Input: $p = "Joe hit a ball, the hit ball flew far after it was hit."
       $w = "hit"
Output: "ball"

The banned word "hit" occurs 3 times.
The other word "ball" occurs 2 times.
Example 2
Input: $p = "Perl and Raku belong to the same family. Perl is the
most popular language in the weekly challenge."
       $w = "the"
Output: "Perl"

The banned word "the" occurs 3 times.
The other word "Perl" occurs 2 times.

I can count all words with a hash, delete the banned entry and then find that with the largest frequency. I use max_by from List::UtilsBy or List::AllUtils. I split the paragraph on non-word characters. This yields a one and a half liner:

Example 1:

perl -MList::UtilsBy=max_by -E '
($w, $p)=@ARGV; ++$c{fc $_} for split /\W+/, $p; delete $c{fc $w};
say "$w\n$p\n->\n", max_by{$c{$_}} keys %c;
' hit "Joe hit a ball, the hit ball flew far after it was hit."

Results:

hit
Joe hit a ball, the hit ball flew far after it was hit.
->
ball

Example 2:

perl -MList::UtilsBy=max_by -E '
($w, $p)=@ARGV; ++$c{fc $_} for split /\W+/, $p; delete $c{$w};
say "$w\n$p\n->\n", max_by{$c{$_}} keys %c;
' the \
  "Perl and Raku belong to the same family. Perl is the
   most popular language in the weekly challenge."

Results:

the
Perl and Raku belong to the same family. Perl is the
   most popular language in the weekly challenge.
->
perl

The full code is similar:

 1  # Perl weekly challenge 255
 2  # Task 2:  Most Frequent Word
 3  #
 4  # See https://wlmb.github.io/2024/02/05/PWC255/#task-2-most-frequent-word
 5  use v5.36;
 6  use List::UtilsBy qw(max_by);
 7  die <<~"FIN" unless @ARGV==2;
 8      Usage: $0 S ¨P
 9      to find the most frequent word in paragraph P excluding the word S
10      FIN
11  my ($w, $p)=@ARGV;
12  my %count;
13  ++$count{fc $_} for split /\W+/, $p;
14  delete $count{fc $w};
15  say "\n$w\n$p\n->\n", max_by{$count{$_}} keys %count;

Examples:

./ch-2.pl hit "Joe hit a ball, the hit ball flew far after it was hit."
./ch-2.pl the \
  "Perl and Raku belong to the same family. Perl is the
   most popular language in the weekly challenge."

Results:

hit
Joe hit a ball, the hit ball flew far after it was hit.
->
ball

the
Perl and Raku belong to the same family. Perl is the
   most popular language in the weekly challenge.
->
perl

/;

Written on February 5, 2024