Perl Weekly Challenge 395.

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

Task 1: Complex Number

Submitted by: Mohammad Sajid Anwar
You are given two complex numbers as string.

Write a script to return the multiplication of the given complex numbers.

Using the formula: (a + bi) x (c + di) = (ac - bd) + (ad + bc)i

Example 1
Input: $num1 = "1+1i", $num2 = "1+1i"
Output: "0+2i"

Example 2
Input: $num1 = "1+(-1)i", $num2 = "1+(-1)i"
Output: "0+(-2)i"

Example 3
Input: $num1 = "0+3i", $num2 = "0+4i"
Output: "-12+0i"

Example 4
Input: $num1 = "3+4i", $num2 = "3+(-4)i"
Output: "25+0i"

Example 5
Input: $num1 = "50+(-20)i", $num2 = "-10+30i"
Output: "100+1700i"

A very simple solution is to use the Perl Data Language PDL, as it understand complex arithmetic. I only have to modify sightly the input syntax. I assume the inputs are strings in @ARGV. I change the string i to the function i() and then eval the result. The code fits a one-liner.

perl -MPDL -E '
for my($x,$y)(@ARGV){($p,$q)=map{eval s/i/*i()/gr}$x,$y;say "$x * $y = ", $p*$q;}
' "1+1i" "1+1i"  "1+(-1)i" "1+(-1)i" "0+3i" "0+4i" "3+4i" "3+(-4)i" "50+(-20)i" "-10+30i"

Results:

1+1i * 1+1i = 2i
1+(-1)i * 1+(-1)i = -2i
0+3i * 0+4i = -12
3+4i * 3+(-4)i = 25
50+(-20)i * -10+30i = 100+1700i

There are a few differences in the output format that I believe are not relevant.

The code above is of course dangerous, as it evals strings that come from the outside. It would be safer to actually parse the input, get the real and imaginary parts and perform the complex multiplication. According to the examples it seems I can assume all complex numbers to have an explicit real and imaginary parts separated by a plus sign. The imaginary part is within parenthesis with an explicit sign if it is negative; no spaces. It is a simple, though not great syntax. The full code becomes:

 1  # Perl weekly challenge 395
 2  # Task 1:  Complex Number
 3  #
 4  # See https://wlmb.github.io/2026/10/18/PWC395/#task-1-complex-number
 5  use v5.36;
 6  use feature qw(try);
 7  die <<~"FIN" unless @ARGV and @ARGV%2==0;
 8      Usage: $0 X0 Y0 X1 Y1...
 9      to multiply the complex numbers Xn and Yn.
10      FIN
11  for my($x, $y)(@ARGV){
12      try{
13          my ($xc, $yc) = map {s2c($_)} $x, $y;
14          my $rc=mult($xc, $yc);
15          say "$x $y -> ", c2s($rc);
16      }
17      catch($e){warn $e;}
18  }
19  sub s2c($n){
20      my $num='[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?';
21      my ($re, $imn, $imp)=$n=~/^($num)\+(?:\((\-$num)\)|($num))i$/;
22      my $im=$imn//$imp;
23      die "Bad format: $n" unless defined $re and defined $im;
24      return [$re, $im];
25  }
26  sub mult($x, $y){
27      return [$x->[0]*$y->[0]-$x->[1]*$y->[1], $x->[0]*$y->[1]+$x->[1]*$y->[0]];
28  }
29  sub c2s($n){
30      return $n->[1]>=0 ? "$n->[0]+$n->[1]i"
31                        : "$n->[0]+($n->[1])i";
32  }
33  

Example:

./ch-1.pl "1+1i" "1+1i"  "1+(-1)i" "1+(-1)i" "0+3i" "0+4i" "3+4i" \
          "3+(-4)i" "50+(-20)i" "-10+30i"

Results:

1+1i 1+1i -> 0+2i
1+(-1)i 1+(-1)i -> 0+(-2)i
0+3i 0+4i -> -12+0i
3+4i 3+(-4)i -> 25+0i
50+(-20)i -10+30i -> 100+1700i

Task 2: Word Squares

Submitted by: Mohammad Sajid Anwar
You are given a list of equal lengths words.

Write a script to arrange a set of words into a grid that reading
across any row gives the exact same word as reading down its
corresponding column.

Example 1
Input: @words = ("MA", "AM", "MY", "ME")
Output: ("MA", "AM")

    M A
    A M

Example 2
Input: @words = ("SUN", "USE", "NET", "SEE", "TEN")
Output: ("SUN", "USE", "NET")

    S U N
    U S E
    N E T

Example 3
Input: @words = ("BOAT", "TEAL", "AREA", "TSAR", "OGRE")
Output: ("BOAT", "OGRE", "AREA", "TEAL")

    B O A T
    O G R E
    A R E A
    T E A L

Example 4
Input: @words = ("CARD", "AREA", "REAR", "DART")
Output: ("CARD", "AREA", "REAR", "DART")

    C A R D
    A R E A
    R E A R
    D A R T

Example 5
Input: @words = ("HEART", "TREND", "EMBER", "RESIN", "ABUSE")
Output: ("HEART", "EMBER", "ABUSE", "RESIN", "TREND")

    H E A R T
    E M B E R
    A B U S E
    R E S I N
    T R E N D

To solve this task I test all possibilities recursively until I find the first solution or find there are no solutions. I try to detect failures early, so that I don’t have to test exhaustively. I make a routine to test possibly incomplete arrays for failures. I don’t test the letters that have already been tested. I make another routine to choose a possible next word and call itself recursively for each viable candidate. The result fits a 4.5 liner.

perl -E '
for(@ARGV){@w=split" ";say "@w -> ", join" ",f([],[@w]);}sub f($c,$r){
return @$c if 0<@$c&&@$c==length$c->[0];for(0..@$r-1){my@r;my @t=(@$c,
$r->[$_]);t(@t)&&(@r=f([@t],[@$r[0..$_-1],@$r[$_+1..@$r-1]]))&&return@r;}
return;}sub t(@t){$i=@t-1;for my$j(0..$i){substr($t[$i],$j,1)eq substr
($t[$j],$i,1)||return 0;}return 1;}
' "MA AM MY ME" \
  "SUN USE NET SEE TEN" \
  "BOAT TEAL AREA TSAR OGRE" \
  "CARD AREA REAR DART" \
  "HEART TREND EMBER RESIN ABUSE"

Results:

MA AM MY ME -> MA AM
SUN USE NET SEE TEN -> SUN USE NET
BOAT TEAL AREA TSAR OGRE -> BOAT OGRE AREA TEAL
CARD AREA REAR DART -> CARD AREA REAR DART
HEART TREND EMBER RESIN ABUSE -> HEART EMBER ABUSE RESIN TREND

The full code is:

 1  # Perl weekly challenge 395
 2  # Task 2:  Word Squares
 3  #
 4  # See https://wlmb.github.io/2026/10/18/PWC395/#task-2-word-squares
 5  use v5.36;
 6  use feature qw(try);
 7  use List::Util qw(all);
 8  die <<~"FIN" unless @ARGV;
 9      Usage: $0 L0 L1...
10      to make a square with the space separated words
11      in list Ln.
12      FIN
13  for(@ARGV){
14      try {
15          my @words = split " ";
16          die "At least one word is required" unless @words >=1;
17          die "Null words are not allowed"
18              unless all {length $_ > 0} @words;
19          die "Only upper case ASCII words allowed"
20              unless all {/^[A-Z]+$/} @words ;
21          die "All words should be of the same length"
22              unless all {length $_ == length $words[0]};
23          die "The number of words should be larger than their length"
24              unless @words >= length $words[0];
25          say "@words -> ", join " ", build([], [@words]);
26      }
27      catch($e){warn $e}
28  }
29  
30  sub build($current, $rest){
31      return @$current if 0 < @$current && @$current == length $current->[0]; # done
32      for(0 .. @$rest - 1){
33          my @result;
34          my @testing = (@$current, $rest->[$_]);
35          test(@testing)
36              && (@result = build([@testing], [@$rest[0..$_-1], @$rest[$_+1..@$rest-1]]))
37              && return @result;
38      }
39      return;
40  }
41  sub test(@t){
42      my $i=@t-1;
43      for my $j(0..$i){
44          substr($t[$i], $j, 1) eq substr($t[$j], $i, 1)
45              || return 0;
46      }
47      return 1;
48  }

Example:

./ch-2.pl "MA AM MY ME" \
          "SUN USE NET SEE TEN" \
          "BOAT TEAL AREA TSAR OGRE" \
          "CARD AREA REAR DART" \
          "HEART TREND EMBER RESIN ABUSE"

Results:

MA AM MY ME -> MA AM
SUN USE NET SEE TEN -> SUN USE NET
BOAT TEAL AREA TSAR OGRE -> BOAT OGRE AREA TEAL
CARD AREA REAR DART -> CARD AREA REAR DART
HEART TREND EMBER RESIN ABUSE -> HEART EMBER ABUSE RESIN TREND

/;

Written on October 18, 2026