Perl Weekly Challenge 390.

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

Task 1: Decode String

Submitted by: Mohammad Sajid Anwar
You are given an encoded string.

Write a script to return the decoded string of the given encoded string.

The encoding rule is: K[encoded_string], where the encoded_string
inside the square brackets is repeated exactly K > 0 times.

Example 1
Input: $str = "2[3[a]]"
Output: "aaaaaa"

3[a]    => aaa
2[3[a]] => aaa aaa

Example 2
Input: $str = "10[a]"
Output: "aaaaaaaaaa"

Example 3
Input: $str = "a2[b]c3[d]e"
Output: "abbcddde"

Example 4
Input: $str = "2[a2[b]c]"
Output: "abbcabbc"

Example 5
Input: $str = "1[a]2[b3[c]]"
Output: "abcccbccc"


I replace repeatedly substrings of the form “N[X]” with N a number and X a substring with no opening nor closing brackets by XXX…X repeated N times. This yields a one-liner.

Examples:

perl -E '
for(@ARGV){$i=$_;1while s/(\d+)\[([^\[\]]*)\]/$2x$1/e;say "$i -> $_";}
' 2[3[a]] 10[a] a2[b]c3[d]e 2[a2[b]c] 1[a]2[b3[c]]

Results:

2[3[a]] -> aaaaaa
10[a] -> aaaaaaaaaa
a2[b]c3[d]e -> abbcddde
2[a2[b]c] -> abbcabbc
1[a]2[b3[c]] -> abcccbccc

The program above may get confused if any bracket is to be taken literally. For example, “2[[]” would not yield “[[”. That would require a more sophisticated parser.

The full code is:

 1  # Perl weekly challenge 390
 2  # Task 1:  Decode String
 3  #
 4  # See https://wlmb.github.io/2026/09/11/PWC390/#task-1-decode-string
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV;
 7      Usage: $0 E0 E1...
 8      to decode the encoded strings En of the form
 9      A or AN[B]C
10      where A is an ordinary string, N a repetition count,
11      and B and C encoded strings.
12      FIN
13  for(@ARGV){
14      my $in = $_;
15      1 while s/
16            (\d+)       # number
17            \[          # opening bracket
18            ([^\[\]]*)  # string without brackets
19            \]          # closing bracket
20           /$2 x $1/xe; # repeat bracketed string
21      say "$in -> $_";
22  }

Example:

./ch-1.pl 2[3[a]] 10[a] a2[b]c3[d]e 2[a2[b]c] 1[a]2[b3[c]]

Results:

2[3[a]] -> aaaaaa
10[a] -> aaaaaaaaaa
a2[b]c3[d]e -> abbcddde
2[a2[b]c] -> abbcabbc
1[a]2[b3[c]] -> abcccbccc

Task 2: Order Characters

Submitted by: Mohammad Sajid Anwar
You are given a string $s (containing only alphabetic
characters) and an integer $k > 0.

Write a script to choose one of the first $k letters of
given string and append it at the end of the string. You
keep doing this until you have lexicographically smallest
string and return the string.

Example 1
Input: $str = "dbca", $k = 1
Output: "adbc"

Move 1: "bcad"
Move 2: "cadb"
Move 3: "adbc"

Example 2
Input: $str = "geeks", $k = 2
Output: "eegks"

First 2 letters: "g", "e"

Move 1: "gekse" (move second letter "e")
Move 2: "gksee" (move second letter "e")
Move 3: "kseeg"
Move 4: "seegk"
Move 5: "eegks"

Example 3
Input: $str = "cbaed", $k = 3
Output: "abcde"

First 3 letters: "c", "b", "a"

Move 1: "cbeda"  (move "a")
Move 2: "cedab"  (move "b")
Move 3: "edabc"  (move "c")
Move 4: "eabcd"  (move "d")
Move 5: "abcde"  (move "e")

Example 4
Input: $str = "fedcba", $k = 4
Output: "abcdef"

First 4 letters: "f", "e", "d", "c"

Move 1: "fdcbae" (move "e")
Move 2: "dcbaef" (move "f")
Move 3: "dcbefa" (move "a")
Move 4: "dcefab" (move "b")
Move 5: "defabc" (move "c")
Move 6: "efabcd" (move "d")
Move 7: "fabcde" (move "e")
Move 8: "abcdef" (move "f")

Example 5
Input: $str = "perl", $k = 1
Output: "erlp"

Move 1: "erlp" (move "p")

Example 6
Input: $str = "oloolooo", $k = 1
Output: "looloooo"

Example 7
Input: $str = "oloooolo", $k = 1
Output: "looloooo"

It is not obvious to me which of the allowed permutations leads to the correct result. The examples show that the lexicographic value might increase in one step before decreasing towards the optimum. Thus, I try all allowed permutations. To that end, I make a recursive function that searches the minimum between the given string, and the function applied to the strings that can be produced through the allowed permutatons. In order to avoid infinite loops I build a hash of seen arguments, and return a trivial result (the identity) if an argument is repeated before the solution is found. I use minstr from List::Util to find the lexicographic minimum out of a list of strings. The result takes a two-liner.

Examples:

perl -MList::Util=minstr -E '
for my($s,$k)(@ARGV){say "$s $k -> ",f($s,$k,{});}sub f($s,$k,$t){return$s if $t->{$s};
$t->{$s}=1;return minstr($s,map {f($s=~s/^(.{$_})(.)(.*)$/$1$3$2/r,$k,$t)}0..$k-1);}
' dbca 1 geeks 2 cbaed 3 fedcba 4 perl 1 oloolooo 1 oloooolo 1

Results:

dbca 1 -> adbc
geeks 2 -> eegks
cbaed 3 -> abcde
fedcba 4 -> abcdef
perl 1 -> erlp
oloolooo 1 -> looloooo
oloooolo 1 -> looloooo

The full code is:

 1  # Perl weekly challenge 390
 2  # Task 2:  Order Characters
 3  #
 4  # See https://wlmb.github.io/2026/09/11/PWC390/#task-2-order-characters
 5  use v5.36;
 6  use List::Util qw(minstr);
 7  die <<~"FIN" unless @ARGV and @ARGV%2==0;
 8      Usage: $0 S0 K0 S1 K1...
 9      to find the minimum string that can be obtained from
10      string Sn by repeatedly moving one of its Kn first characters
11      to the end.
12      FIN
13  for my($string, $k)(@ARGV){
14      say "$string $k -> ", order($string, $k, {});
15  }
16  sub order($string, $k, $seen){
17      return $string if $seen->{$string};   # Avoid infinite recursion
18      $seen->{$string} = 1;
19      return minstr (
20          $string,
21          map {order(
22                   $string =~ s/^(.{$_})(.)(.*)$/$1$3$2/r,
23                   $k,
24                   $seen
25                   )
26          } 0..$k-1);
27  }

Examples:

./ch-2.pl dbca 1 geeks 2 cbaed 3 fedcba 4 perl 1 oloolooo 1 oloooolo 1

Results:

dbca 1 -> adbc
geeks 2 -> eegks
cbaed 3 -> abcde
fedcba 4 -> abcdef
perl 1 -> erlp
oloolooo 1 -> looloooo
oloooolo 1 -> looloooo

As could have been expected, I obtained deep recursion warnings. For the example fedcba 4 above, I had recursion depths above 600. So my solutions above are not too robust.

/;

Written on September 11, 2026