Perl Weekly Challenge 315.

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

Task 1: Find Words

Submitted by: Mohammad Sajid Anwar
You are given a list of words and a character.

Write a script to return the index of word in the list where you find the given character.


Example 1
Input: @list = ("the", "weekly", "challenge")
       $char = "e"
Output: (0, 1, 2)

Example 2
Input: @list = ("perl", "raku", "python")
       $char = "p"
Output: (0, 2)

Example 3
Input: @list = ("abc", "def", "bbb", "bcd")
       $char = "b"
Output: (0, 2, 3)

I solve this straightforwardly using a Schwartzian transform of the words in the list, filtering the resulting list by the presence of the character and printing the surviving indices. The code fits a 1.5-liner.

Example 1:

perl -E '
($c,@x)=@ARGV;say "char: $c, words: @x -> ", join ",", map {$_->[0]} grep {$_->[1]=~/$c/}
map{[$_, $x[$_]]}0..@x-1
' e the weekly challenge

Results:

char: e, words: the weekly challenge -> 0,1,2

perl -E '
($c,@x)=@ARGV;say "char: $c, words: @x -> ", join ",", map {$_->[0]} grep {$_->[1]=~/$c/}
map{[$_, $x[$_]]}0..@x-1
' p perl raku python

Results:

char: p, words: perl raku python -> 0,2

perl -E '
($c,@x)=@ARGV;say "char: $c, words: @x -> ", join ",", map {$_->[0]} grep {$_->[1]=~/$c/}
map{[$_, $x[$_]]}0..@x-1
' b abc def bbb bcd

Results:

char: b, words: abc def bbb bcd -> 0,2,3

The full code is similar:

 1  # Perl weekly challenge 315
 2  # Task 1:  Find Words
 3  #
 4  # See https://wlmb.github.io/2025/03/31/PWC315/#task-1-find-words
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV>=2;
 7      Usage: $0 C W0 W1...
 8      to find the indices of the words Wn that contain the character C
 9      FIN
10  my $char = shift;
11  die "Expected a single char" unless $char=~/^\w$/;
12  say "char: $char, words: @ARGV -> ",
13      join ",",
14          map {$_->[0]}           # Extract indices
15          grep {$_->[1]=~/$char/} # Test word
16          map{[$_, $ARGV[$_]]}    # Schwartzian transform
17          0..@ARGV-1;

Example:

./ch-1.pl e the weekly challenge
./ch-1.pl p perl raku python
./ch-1.pl b abc def bbb bcd

Results:

char: e, words: the weekly challenge -> 0,1,2
char: p, words: perl raku python -> 0,2
char: b, words: abc def bbb bcd -> 0,2,3

Task 2: Find Third

Submitted by: Mohammad Sajid Anwar
You are given a sentence and two words.

Write a script to return all words in the given sentence that appear
in sequence to the given two words.


Example 1
Input: $sentence = "Perl is a my favourite language but Python is my favourite too."
       $first = "my"
       $second = "favourite"
Output: ("language", "too")

Example 2
Input: $sentence = "Barbie is a beautiful doll also also a beautiful princess."
       $first = "a"
       $second = "beautiful"
Output: ("doll", "princess")

Example 3
Input: $sentence = "we will we will rock you rock you.",
       $first = "we"
       $second = "will"
Output: ("we", "rock")

I could solve the problem by building a regular expression to repeatedly fetch the word that follows the first two given words. This fits a long one-liner.

Example 1 (wrong, see below):

perl -E '
($f,$s,$r)=@ARGV;$e="$f\\W+$s\\W+(\\w+)";@o=$r=~/$e/g;say "first: $f, second: $s, \nsentence: $r\n-> @o"
' my favourite "Perl is my favourite language but Python is my favourite too."

Results:

first: my, second: favourite,
sentence: Perl is my favourite language but Python is my favourite too.
-> language too

Example 2:

perl -E '
($f,$s,$r)=@ARGV;$e="$f\\W+$s\\W+(\\w+)";@o=$r=~/$e/g;say "first: $f, second: $s, \nsentence: $r\n-> @o"
' a beautiful "Barbie is a beautiful doll also also a beautiful princess."

Results:

first: a, second: beautiful,
sentence: Barbie is a beautiful doll also also a beautiful princess.
-> doll princess

Example 3:

perl -E '
($f,$s,$r)=@ARGV;$e="$f\\W+$s\\W+(\\w+)";@o=$r=~/$e/g;say "first: $f, second: $s, \nsentence: $r\n-> @o"
' we will "we will we will rock you rock you"

Results:

first: we, second: will,
sentence: we will we will rock rock you rock you
-> we

Note that example 3 failed, as the second we is eaten away by the first match. In general, the /g modifier starts a repeated search where the previous one ended. We can avoid eating all the previously matched string by using a lookahead assertion. In the following code we just eat the first word, but keep from the second word onwards by adding a lookahead assertion into our regular expression.

Example 3’:

perl -E '
($f,$s,$r)=@ARGV;$e="$f\\W+(*pla:$s\\W+(\\w+))";@o=$r=~/$e/g;
say "first: $f, second: $s, \nsentence: $r\n-> @o"
' we will "we will we will rock you rock you"

Results:

first: we, second: will,
sentence: we will we will rock you rock you
-> we rock

This fixes example 3. We still have to verify examples 1 and 2 continue working:

Examples 1’ and 2’

perl -E '
($f,$s,$r)=@ARGV;$e="$f\\W+(*pla:$s\\W+(\\w+))";@o=$r=~/$e/g;
say "first: $f, second: $s, \nsentence: $r\n-> @o"
' my favourite "Perl is my favourite language but Python is my favourite too."
perl -E '
($f,$s,$r)=@ARGV;$e="$f\\W+(*pla:$s\\W+(\\w+))";@o=$r=~/$e/g;
say "first: $f, second: $s, \nsentence: $r\n-> @o"
' a beautiful "Barbie is a beautiful doll also also a beautiful princess."

Results:

first: my, second: favourite,
sentence: Perl is my favourite language but Python is my favourite too.
-> language too
first: a, second: beautiful,
sentence: Barbie is a beautiful doll also also a beautiful princess.
-> doll princess

The full code is:

 1  # Perl weekly challenge 315
 2  # Task 2:  Find Third
 3  #
 4  # See https://wlmb.github.io/2025/03/31/PWC315/#task-2-find-third
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV==3;
 7      Usage: W1 W2 S
 8      to find which words in sentence S follows words W1 and W2.
 9      FIN
10  my ($first, $second, $sentence)=@ARGV;
11  for($first, $second){die "Expected a single word: $_" unless /^\w+$/}
12  my $re="$first\\W+(*pla:$second\\W+(\\w+))";
13  my @output=$sentence=~/$re/g;
14  say "first: $first, second: $second, \nsentence: $sentence\n-> @output"

Example:

./ch-2.pl my favourite "Perl is my favourite language but Python is my favourite too."
./ch-2.pl a beautiful "Barbie is a beautiful doll also also a beautiful princess."
./ch-2.pl we will "we will we will rock you rock you"

Results:

first: my, second: favourite,
sentence: Perl is my favourite language but Python is my favourite too.
-> language too
first: a, second: beautiful,
sentence: Barbie is a beautiful doll also also a beautiful princess.
-> doll princess
first: we, second: will,
sentence: we will we will rock you rock you
-> we rock

/;

Written on March 31, 2025