<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bob Lied</title>
    <description>The latest articles on DEV Community by Bob Lied (@boblied).</description>
    <link>https://dev.to/boblied</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F470960%2F3925166c-2844-4880-92af-2dfede66665b.jpeg</url>
      <title>DEV Community: Bob Lied</title>
      <link>https://dev.to/boblied</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/boblied"/>
    <language>en</language>
    <item>
      <title>PWC 397: Reflection</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Sat, 31 Oct 2026 00:19:19 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-397-reflection-2dcd</link>
      <guid>https://dev.to/boblied/pwc-397-reflection-2dcd</guid>
      <description>&lt;p&gt;October ends with a plaintive little offering from &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-397/" rel="noopener noreferrer"&gt;the weekly challenge&lt;/a&gt;. It asks us to consider the negative and liminal space just beyond the surface -- to search for what is missing; to create an order that is mysteriously irrational yet trivially banal; to contemplate what it is we yearn for. Listen to &lt;a href="https://www.youtube.com/watch?v=Zv0OwvsP0ek" rel="noopener noreferrer"&gt;Wishing You Were Here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-397/#TASK1" rel="noopener noreferrer"&gt;Task 1: Absent Smallest Positive&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The task
&lt;/h3&gt;

&lt;p&gt;You are given an array of integers. Write a script to return the smallest absent positive integer such that it is strictly greater than the average of all elements in the given array.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 1
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (1, 2, 4, 5, 6)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;7&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Average: (1 + 2 + 4 + 5 + 6) / 5 = 3.6&lt;/li&gt;
&lt;li&gt;We need the smallest positive integer absent from nums that is strictly greater than 3.6. The positive integers greater than 3.6 are 4, 5, 6, ...&lt;/li&gt;
&lt;li&gt;The smallest missing one is 7.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example 2
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (-5, -2, -1, 3)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;1&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;The average is -1.25. There is a gap in the array between -1 and 3. The smallest positive integer in the gap is 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example 3
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (1, 2, 3)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;4&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;The average is 2. The array ends at 3. The smallest positive integer missing from the array is 4.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example 4
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (2, 3, 7, 8)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;6&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;The average is 5. 6 is greater and missing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example 5
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (1, 1, 1, 10)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Output:_ &lt;code&gt;4&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;The average is 3.25, 4 is the smallest absent integer.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The wheels turn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Clearly we need to first make one pass over the array to find the average. &lt;/li&gt;
&lt;li&gt;A negative average promotes to 0, because we only want to look at numbers that are positive.&lt;/li&gt;
&lt;li&gt; We can ignore all numbers less than the average.&lt;/li&gt;
&lt;li&gt;Although the examples all have numbers in ascending order, we shouldn't assume that.&lt;/li&gt;
&lt;li&gt;It sure is going to be easier to find gaps if the array is sorted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, let's try finding the average; filtering the array; sorting; and walking up the array to find gaps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="nf"&gt;arr&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt;    &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@arr&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@arr&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;List::&lt;/span&gt;&lt;span class="nv"&gt;Util&lt;/span&gt; &lt;span class="sx"&gt;qw/sum0/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;sum0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;@arr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;@arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$start&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@arr&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$beg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$start&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="nv"&gt;@arr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$beg&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$beg&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="k"&gt;continue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$beg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$end&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$beg&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can begin by dispensing with the edge cases of empty and singleton arrays, where the answer is obvious.&lt;/li&gt;
&lt;li&gt;Next we want the average. The average is going to be a lower bound, so I'm naming it &lt;code&gt;$start&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The while loop is going to consider the intervals between  consecutive values of the array, named as &lt;code&gt;$beg&lt;/code&gt; and &lt;code&gt;$end&lt;/code&gt;. We will destroy &lt;code&gt;@arr&lt;/code&gt; by lopping off the leading value each time through the loop.

&lt;ul&gt;
&lt;li&gt; If the difference is not 1, then there is a gap, and we can take the value after &lt;code&gt;$beg&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I'm going to be cute here and use the obscure &lt;code&gt;continue&lt;/code&gt; block of the &lt;code&gt;while&lt;/code&gt; to reset &lt;code&gt;$beg&lt;/code&gt;. This is completely gratuitous, but it does call out the boundary of the interval in a kind of readable way.
&lt;/li&gt;
&lt;li&gt;If there are no gaps in the array, then we finish the loop and need to return something bigger than the last element. The &lt;code&gt;while&lt;/code&gt; loop finished by assigning &lt;code&gt;$beg&lt;/code&gt; to the last element that was shifted, and then failing to shift again. So at the end of the loop, &lt;code&gt;$beg&lt;/code&gt; is the last element of the array, and &lt;code&gt;$end&lt;/code&gt; is undefined.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-397/#TASK2" rel="noopener noreferrer"&gt;Task 2: Binary Reflection&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The task
&lt;/h3&gt;

&lt;p&gt;You are given an array of integer. Write a script to sort the given array in ascending order based on the binary reflection of each element. If two different numbers have the same binary reflection, the smaller original number should appear first.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 1
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Input:_ &lt;code&gt;@arr = (3, 6, 12)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;(3, 6, 12)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Decimal 3  = Binary   11 &amp;lt;|&amp;gt; 11   = Decimal 3
    Decimal 6  = Binary  110 &amp;lt;|&amp;gt; 011  = Decimal 3
    Decimal 12 = Binary 1100 &amp;lt;|&amp;gt; 0011 = Decimal 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three elements have the same binary reflection (3). Since they tie, they are sorted by their original values in ascending order: (3, 6, 12).&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 2
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (1, 2, 4, 8)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;(1, 2, 4, 8)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Decimal 1 = Binary    1 &amp;lt;|&amp;gt; 1 = Decimal 1
Decimal 2 = Binary   10 &amp;lt;|&amp;gt; 01 = Decimal 1
Decimal 4 = Binary  100 &amp;lt;|&amp;gt; 001 = Decimal 1
Decimal 8 = Binary 1000 &amp;lt;|&amp;gt; 0001 = Decimal 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All elements reflect to 1. Tie-breaking by original value yields (1, 2, 4, 8).&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 3
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (7, 8, 9, 10)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; (&lt;code&gt;8, 10, 7, 9)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Decimal 8  = Binary 1000 &amp;lt;|&amp;gt; 0001 = Decimal 1
Decimal 9  = Binary 1001 &amp;lt;|&amp;gt; 1001 = Decimal 9
Decimal 10 = Binary 1010 &amp;lt;|&amp;gt; 0101 = Decimal 5
Decimal 7  = Binary  111 &amp;lt;|&amp;gt; 111  = Decimal 7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sorting by reflection values (1, 5, 7, 9) gives original elements (8, 10, 7, 9).&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 4
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (5, 9, 15, 17)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;(5, 9, 15, 17)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Decimal 5  = Binary   101 &amp;lt;|&amp;gt; 101   = Decimal 5
Decimal 9  = Binary  1001 &amp;lt;|&amp;gt; 1001  = Decimal 9
Decimal 15 = Binary  1111 &amp;lt;|&amp;gt; 1111  = Decimal 15
Decimal 17 = Binary 10001 &amp;lt;|&amp;gt; 10001 = Decimal 17
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All numbers are binary palindromes, so their reflections match their original decimal values (5, 9, 15, 17), leaving the array order unchanged.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 5
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (11, 13, 14, 19)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;(14, 13, 11, 19)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Decimal 11 = Binary  1011 &amp;lt;|&amp;gt; 1101  = Decimal 13
Decimal 13 = Binary  1101 &amp;lt;|&amp;gt; 1011  = Decimal 11
Decimal 14 = Binary  1110 &amp;lt;|&amp;gt; 0111  = Decimal 7
Decimal 19 = Binary 10011 &amp;lt;|&amp;gt; 11001 = Decimal 25
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sorted by reflection values (7, 11, 13, 25) yields (14, 13, 11, 19).&lt;/p&gt;

&lt;h1&gt;
  
  
  The hard part, thinking
&lt;/h1&gt;

&lt;p&gt;There are two parts: determining binary reflection values, and sorting. &lt;/p&gt;

&lt;p&gt;Inside you there are two wolves. The first wolf learned to program in C, and sees this as a bit-twiddling exercise. The other wolf programs in Perl, and sees this as an obvious case of reversing a string. Which wolf wins? The lazy one, of course.&lt;/p&gt;

&lt;p&gt;For sorting, we want the reflected values at hand, so this is going to be a variation on the &lt;a href="https://en.wikipedia.org/wiki/Schwartzian_transform" rel="noopener noreferrer"&gt;Schwartzian transform&lt;/a&gt;. Augment each number in the array with a pair -- the original number, and its binary reflection. Sort the array of pairs, then take the original number out of each pair.&lt;/p&gt;

&lt;h3&gt;
  
  
  The code please, maestro
&lt;/h3&gt;

&lt;p&gt;First, a little function to do binary reflection. This seems like it would be a good candidate for Memoize to cache values of repeated calls. I include that in the code snippet here, but my performance tests showed negligible improvement. This seems to be one of those cases where the overhead of memo-ization isn't justified by the relatively trivial body of the function.&lt;/p&gt;

&lt;p&gt;To get a binary representation, I'm using &lt;code&gt;sprintf&lt;/code&gt; with a binary format string, &lt;code&gt;%b&lt;/code&gt;. Then I want to reverse the string and turn it back into an integer. Old bit-twiddlers like me know that the function that does that is &lt;code&gt;oct()&lt;/code&gt;, but it requires a &lt;code&gt;0b&lt;/code&gt; prefix to recognize binary strings. Rather than perform another string append operation, I just snuck &lt;code&gt;b0&lt;/code&gt; into the end of the format, which becomes &lt;code&gt;0b&lt;/code&gt; on reversal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;Memoize&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;memoize&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;');&lt;/span&gt;
&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;reflect&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;oct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;reverse&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;%bb0&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For sorting, I want to augment the input array with reflection information.&lt;/p&gt;

&lt;p&gt;There are two ways to go: I can set up an auxiliary lookup table and enter all the reflected values there. Then sort the array by referencing the table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%mirror&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$mirror&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$mirror&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or I can tag each of the original values with its reflected value. In practical terms, I turn each of the original integers into a pair of numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, the sort indexes the pair for comparison&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However that yields an array of pairs, so that needs to be manipulated again to extract only the first member of each pair:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In idiomatic form, this is written in a single statement as a map/sort/map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Between the two possibilities, the tradeoff is that the lookup hash has overhead for each access, but can potentially have fewer entries. The array approach has quick indexed access, but doubles the space required.&lt;/p&gt;

&lt;p&gt;A benchmark shows that, at least in my environment, using the transform with pair arrays is about 15% faster.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>challenge</category>
      <category>coding</category>
      <category>programming</category>
    </item>
    <item>
      <title>PWC 396: Finishing Order, Trionic Array</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Sat, 24 Oct 2026 14:30:17 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-396-finishing-order-trionic-array-57h2</link>
      <guid>https://dev.to/boblied/pwc-396-finishing-order-trionic-array-57h2</guid>
      <description>&lt;p&gt;It's a lovely Saturday morning in Wisconsin, and I feel like writing a few words about &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-396/" rel="noopener noreferrer"&gt;Weekly Challenge 396&lt;/a&gt;, which I finished earlier this week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1:  Finishing Order
&lt;/h2&gt;

&lt;p&gt;You are given two arrays of integers, &lt;code&gt;@order&lt;/code&gt; and &lt;code&gt;@friends&lt;/code&gt;. The &lt;code&gt;@order&lt;/code&gt; array (size &lt;em&gt;n&lt;/em&gt;) contains every integer from 1 to &lt;em&gt;n&lt;/em&gt; exactly once. The &lt;code&gt;@friends&lt;/code&gt; array contains ID sorted in strictly increasing order. Write a script to return the array containing IDs in finishing order.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@order = (3, 1, 4, 2, 5)&lt;/code&gt;
&lt;code&gt;@friends = (1, 2, 4)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;(1, 4, 2)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;ID 1 finished 2nd, ID 4 finished 3rd, ID 2 finished 4th.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;_Input: &lt;code&gt;@order = (5, 4, 3, 2, 1)&lt;/code&gt;
&lt;code&gt;@friends = (1, 3, 5)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;(5, 3, 1)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;ID 5 finished 1st, ID 3 finished 3rd, ID 1 finished 5th.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 3:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@order = (2, 4, 1, 3)&lt;/code&gt;
&lt;code&gt;@friends = (1, 2, 3, 4)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;(2, 4, 1, 3)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;ID 2 finished 1st, ID 4 finished 2nd, ID 1 finished 3rd, ID 3 finished 4th.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 4:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@order = (4, 1, 3, 2)&lt;/code&gt;
&lt;code&gt;@friends = (3)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;(3)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 5:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@order = (1, 3, 2, 6, 5, 4)&lt;/code&gt;
&lt;code&gt;@friends = (1, 2, 3)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;(1, 3, 2)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;ID 1 finished 1st, ID 3 finished 2nd, ID 2 finished 3rd.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Analysis
&lt;/h3&gt;

&lt;p&gt;Using small numbers as the participants' identifiers makes this a little more confusing than it needs to be. If we modify it to use strings for participants and friends, it's a little clearer. Example 1 might then look like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@order = (carol, alice, dave, bob, ed)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@friends = (alice, bob, dave)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Output: (alice, dave, bob)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then it's a litte easier to see that this task amounts to extracting the &lt;code&gt;@friends&lt;/code&gt; subset from &lt;code&gt;@order&lt;/code&gt;, in the order that they appear.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@order&lt;/code&gt; array is not good for looking up participants; it maps the finishing place to the participant and requires some kind of search.  It would be convenient if we had a table that went the other way, from participant to place. If we had a hash table that maps friends to their finishing place, then we could use that to sort the friends array.&lt;/p&gt;

&lt;h2&gt;
  
  
  Synthesis
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;friends&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%place&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$order&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$place&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$place&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$friends&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;map&lt;/code&gt; statement inverts the &lt;code&gt;@order&lt;/code&gt; array and gives us a hash to look up participants. The task has helpfully specified that there are no duplicates, so the 1-to-1 mapping can safely be inverted.&lt;/li&gt;
&lt;li&gt;Now we can sort &lt;code&gt;@friends&lt;/code&gt; by their finish order.&lt;/li&gt;
&lt;li&gt;Wrapping the result of the &lt;code&gt;sort&lt;/code&gt; in square brackets creates an array reference. I prefer to return references because it avoids data copies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Task 2: Trionic Array
&lt;/h2&gt;

&lt;p&gt;You are given an array of integers. Write a script to return true if the given array is trionic; otherwise return false. An array is trionic if there exist indices 0 &amp;lt; p &amp;lt; q &amp;lt; n−1 such that arr[0..p] is strictly increasing, arr[p..q] is strictly decreasing, and arr[q..n−1] is strictly increasing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (1, 3, 5, 4, 2, 6, 8)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt;&lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (1, 4, 4, 2, 1, 3, 5)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 3:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (2, 10, 3, 1, 9)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 4:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (1, 2, 3, 4, 3, 2, 1)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 5:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@arr = (1, 3, 6, 4, 2, 7, 8, 4)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Analysis
&lt;/h3&gt;

&lt;p&gt;In more intuitive terms, "trionic" seems to mean the array ascends to a peak, comes back down to a valley, and finishes by ascending again. The examples give us some explanatory data, like what to do with repeated values.&lt;/p&gt;

&lt;p&gt;One thing we can note is that the array must have a minimum of four elements to form a peak and a valley.&lt;/p&gt;

&lt;p&gt;The simplest thing that could work is to scan the array for peaks and valleys and check that there is exactly one of each. So let's do that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Synthesis
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="nf"&gt;arr&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;false&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;@arr&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
                 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$peak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$valley&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$i&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$#arr&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$peak&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$valley&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$peak&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$valley&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We start by eliminating some easy cases. As noted, there must be at least four elements. Also, it must start and end with an ascending pair.&lt;/li&gt;
&lt;li&gt;The meat of the function is to check each point to see if it's an inflection. Our &lt;code&gt;for&lt;/code&gt; loop indexes inside the ends of the array, so that when we add or subtract 1 from &lt;code&gt;$i&lt;/code&gt; we are guaranteed to still be within the bounds of the array.&lt;/li&gt;
&lt;li&gt;I don't see any cleverness that avoids making a pass through the array and checking the slope. There might be other ways to encode that information -- ascending as 1, descending as -1; or 'U' and 'D' as strings -- and therefore finding peaks and valleys could be done as array reductions or regular expression matches. But I'm not seeing that as more efficient or clearer, so let's not.&lt;/li&gt;
&lt;li&gt;There might be an optimization to leave the loop early as soon as &lt;code&gt;$peak&lt;/code&gt; or &lt;code&gt;$valley&lt;/code&gt; exceeds 1, but the test for the condition at every point might cost as more in execution than simply finishing the loop. It would depend on the data. If the arrays were typically long and irregular so that very few of them are trionic, it might be worth it.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
    <item>
      <title>PWC 393 Triangles and Primes</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Fri, 02 Oct 2026 03:46:25 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-393-triangles-and-primes-4fej</link>
      <guid>https://dev.to/boblied/pwc-393-triangles-and-primes-4fej</guid>
      <description>&lt;p&gt;A couple of quick mathematical tasks for this week's challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-393/#TASK1" rel="noopener noreferrer"&gt;Task 1: Pythagoras Multiplied&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Task Description
&lt;/h3&gt;

&lt;p&gt;You are given a positive integer &lt;em&gt;n&lt;/em&gt;. Find the number of all positive integer triplets (&lt;em&gt;a,b,c&lt;/em&gt;) so that &lt;em&gt;a&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt; + &lt;em&gt;b&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt; = &lt;em&gt;c&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt; and &lt;em&gt;a&lt;/em&gt;, &lt;em&gt;b&lt;/em&gt;, and &lt;em&gt;c&lt;/em&gt; are integers &amp;lt;= &lt;em&gt;n&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt; n=20 --&amp;gt; 12&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(3,4,5),(4,3,5),(5,12,13),(6,8,10),(8,6,10),(8,15,17),(9,12,15),(12,5,13),(12,9,15),(12,16,20),(15,8,17),(16,12,20)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt; n=7 --&amp;gt; 2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Example 3:&lt;/strong&gt; n=1 --&amp;gt; 0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Example 4:&lt;/strong&gt; n=15 --&amp;gt; 8&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Example 5:&lt;/strong&gt; n=30 --&amp;gt; 22&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Task Discussion
&lt;/h3&gt;

&lt;p&gt;We notice from Example 1 that order matters: (3,4,5) is counted as distinct from (4,3,5).&lt;/p&gt;

&lt;p&gt;We know from the geometry of right triangles that there are no integer solutions where &lt;em&gt;a&lt;/em&gt;=&lt;em&gt;b&lt;/em&gt; (an equilateral right triangle has hypotenuse &lt;code&gt;sqrt(2)*a&lt;/code&gt;), so all valid triples will have &lt;em&gt;a&lt;/em&gt;≠&lt;em&gt;b&lt;/em&gt;≠&lt;em&gt;c&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I'm going to start by using brute force, and then thinking about optimizing. For every &lt;em&gt;c&lt;/em&gt; from 1 to &lt;em&gt;n&lt;/em&gt;, there is a target hypotenuse c&lt;sup&gt;2&lt;/sup&gt;. Check every pair of &lt;em&gt;a&lt;/em&gt; and &lt;em&gt;b&lt;/em&gt; from 1 to &lt;em&gt;n&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;First optimization: the first possible triple is (3,4,5), so there's no need to check for &lt;em&gt;c&lt;/em&gt; less than 5.&lt;/p&gt;

&lt;p&gt;Second optimization: if (&lt;em&gt;a,b,c&lt;/em&gt;) works, then so does (&lt;em&gt;b,a,c&lt;/em&gt;). No need to check every combination of &lt;em&gt;a&lt;/em&gt; and &lt;em&gt;b&lt;/em&gt;, just the distinct pairs.&lt;/p&gt;

&lt;p&gt;Third optimization: no need to iterate every value of &lt;em&gt;a&lt;/em&gt; from 1 to &lt;em&gt;n&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The minimum value of &lt;em&gt;a&lt;/em&gt; is 3, because we know that the first valid triple is (3,4,5).&lt;/li&gt;
&lt;li&gt;We know that as &lt;em&gt;a&lt;/em&gt; increases, &lt;em&gt;b&lt;/em&gt; must decrease, so that the maximum value of &lt;em&gt;a&lt;/em&gt; implies the minimum value of &lt;em&gt;b&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;b&lt;/em&gt; will iterate over values greater than &lt;em&gt;a&lt;/em&gt;, so the minimum that &lt;em&gt;b&lt;/em&gt; can ever be is 4.&lt;/li&gt;
&lt;li&gt;We know that &lt;em&gt;a&lt;/em&gt; = sqrt(&lt;em&gt;c&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt; - &lt;em&gt;b&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt;), so the upper bound on &lt;em&gt;a&lt;/em&gt; can be &lt;em&gt;floor(sqrt(c&lt;sup&gt;2&lt;/sup&gt; - 16))&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fourth optimization: no need to iterate every value of &lt;em&gt;b&lt;/em&gt; either. The values of &lt;em&gt;b&lt;/em&gt; will start from &lt;em&gt;a&lt;/em&gt;+1, and increment until the sum exceeds &lt;em&gt;c&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt;. We know that &lt;em&gt;b&lt;/em&gt; = sqrt(&lt;em&gt;c&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt; - &lt;em&gt;a&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt;), so that can be the bound for any given &lt;em&gt;c&lt;/em&gt; and &lt;em&gt;a&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Task Solution
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$c*$c&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$c*$c&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$a*$a&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$a*$a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$b*$b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$c*$c&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;# If a,b works, then so does b,a&lt;/span&gt;
                    &lt;span class="nv"&gt;$count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-393/#TASK2" rel="noopener noreferrer"&gt;Task 2: Prime Step&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Task Description
&lt;/h3&gt;

&lt;p&gt;You are given a string with English alphabetic characters only. What is the absolute difference of the sum of the ASCII values of the characters in the string to the nearest prime number?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "hello"&lt;/code&gt; &lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;9&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ordinal values of "hello" are [104,101,108,108,111], summing up to 532. The nearest prime number to 532 is 523, resulting in an absolute difference of 9.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "football"&lt;/code&gt; &lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;2&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starting with the values [102,111,111,116,98,97,108,108] and the sum 841. We find 839 as the nearest prime number, so the difference is 2.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 3:&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "a"&lt;/code&gt; &lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;0&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The value of "a" is 97, which is a prime number.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 4:&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "challenge"&lt;/code&gt; &lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;2&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ordinal values of "challenge" are [99, 104, 97, 108, 108, 101, 110, 103, 101], which sum up to 931. The nearest prime number to 931 is 929, so the difference is 2.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 5:&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; $str = &lt;code&gt;"perl"&lt;/code&gt; &lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;2&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ordinal values of "perl" are [112, 101, 114, 108], summing up to 435. Nearest prime is 433, so the difference is 2.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Task Discussion
&lt;/h3&gt;

&lt;p&gt;There are several little sub-problems in this task, but all of them have solutions in Perl libraries. Notably, finding the nearest prime efficiently is probably an interesting problem in number theory and computation, but I'm not going to solve it as a side quest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Task Solution
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;List::&lt;/span&gt;&lt;span class="nv"&gt;Util&lt;/span&gt; &lt;span class="sx"&gt;qw/sum0 min/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Math::Prime::&lt;/span&gt;&lt;span class="nv"&gt;Util&lt;/span&gt; &lt;span class="sx"&gt;qw/is_prime prev_prime next_prime/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;sum0&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;ord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;split&lt;/span&gt; &lt;span class="sr"&gt;//&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;is_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;prev_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;next_prime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Perl knowledge required is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;code&gt;ord()&lt;/code&gt; function exists that gives the ASCII value of English letters.&lt;/li&gt;
&lt;li&gt;Library functions exist to sum a list and find the minimum of a list.&lt;/li&gt;
&lt;li&gt;A CPAN module exists for finding prime numbers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The possibly confusing line that does most of the work evaluates from right to left&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;sum0&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;ord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;split&lt;/span&gt; &lt;span class="sr"&gt;//&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;split //, $str&lt;/code&gt; -- change string into an array of individual characters&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;map { ord($_) }&lt;/code&gt; -- transform each character into its ASCII value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sum0&lt;/code&gt; -- add the ordinal values, returning zero if the list is empty&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rest is calls to subroutines in &lt;code&gt;Math::Prime::Util&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
    <item>
      <title>PWC 391 Median Boxes</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Thu, 17 Sep 2026 22:00:08 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-391-median-boxes-27o4</link>
      <guid>https://dev.to/boblied/pwc-391-median-boxes-27o4</guid>
      <description>&lt;p&gt;The first task asks us to combine sorted arrays and find the median, and the second asks us to combine boxes by stacking them inside each other. I feel the urge to merge. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-391/#TASK1" rel="noopener noreferrer"&gt;Task 1: Array Median&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The median is the middle point in a sorted list. Our musical selection should a couple of songs titled 'The Middle', one by &lt;a href="https://www.youtube.com/watch?v=oKsxPW6i3pM" rel="noopener noreferrer"&gt;Jimmy Eat World&lt;/a&gt; (warning, the video features a lot of people in underwear, probably NSFW), and the other by &lt;a href="https://www.youtube.com/watch?v=M3mJkSqZbX4" rel="noopener noreferrer"&gt;Zedd, Maren Morris, and Grey&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Task Description
&lt;/h3&gt;

&lt;p&gt;You are given two sorted arrays. Write a script to merge the two given sorted arrays and return the median of the merged array.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example 1:&lt;/strong&gt; Input: &lt;code&gt;@arr1 = (2), @arr2 = (4)&lt;/code&gt; Output: &lt;code&gt;3.0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 2:&lt;/strong&gt; Input: &lt;code&gt;@arr1 = (1,2,3), @arr2 = (7,8,9,10)&lt;/code&gt; Output: &lt;code&gt;7.0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 3:&lt;/strong&gt; Input: &lt;code&gt;@arr1 = (), @arr2 = (10,20,30,40)&lt;/code&gt; Output: &lt;code&gt;25.0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 4:&lt;/strong&gt; Input: &lt;code&gt;@arr1 = (100), @arr2 = (1,2,3,4,5,6,7)&lt;/code&gt; Output: &lt;code&gt;4.5&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 5:&lt;/strong&gt; Input: &lt;code&gt;@arr1 = (1,2,2), @arr2 = (2,2,3)&lt;/code&gt;
Output: &lt;code&gt;2.0&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Task Solution
&lt;/h3&gt;

&lt;p&gt;The obvious thing to do here is to sort the two arrays together and index into the middle of the combined array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task1&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;arr1&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;arr2&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@all&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$arr1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$arr2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@all&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@all&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Odd number of elements&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$all&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@all&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="c1"&gt;# Even number of elements&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@all&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$all&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$all&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$mid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="c1"&gt;# No elements, two empty lists were given&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another obvious thing to do is to use any of several modules that do statistics.  Here are three possibilities. Each of them follows the pattern of loading the data into the module, and then invoking a &lt;code&gt;median&lt;/code&gt; function on the loaded data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task2&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;arr1&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;arr2&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;@$arr1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;@$arr2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Statistics::Basic::&lt;/span&gt;&lt;span class="nv"&gt;Median&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nn"&gt;Statistics::Basic::&lt;/span&gt;&lt;span class="nv"&gt;Median&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$arr1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$arr2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task3&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;arr1&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;arr2&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;@$arr1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;@$arr2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Statistics::&lt;/span&gt;&lt;span class="nv"&gt;Descriptive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$stat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Statistics::Descriptive::&lt;/span&gt;&lt;span class="nv"&gt;Full&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$stat&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;add_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$arr1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$arr2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$stat&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;median&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task4&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;arr1&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;arr2&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;@$arr1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;@$arr2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;PDL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pdl&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$arr1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$arr2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;median&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of these solutions have quite a bit of overhead because they require sorting the data. We are given that the arrays are already sorted individually, so there's a much more efficient solution: merge the arrays in one pass.  And because we only want the midpoint, we don't even have to merge completely -- we can stop after we've reached the midpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;arr1&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;arr2&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;undef&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;@$arr1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;@$arr2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Make copies of arr1 and arr2 because we're going to destroy them&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@a1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$arr1&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@a2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$arr2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@a1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;@a2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$length&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$isOdd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$length&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@merged&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@a1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;@a2&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;@merged&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nv"&gt;$mid&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@merged&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$a1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$a2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@a1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@a2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# At this point, if we haven't merged enough elements to reach&lt;/span&gt;
    &lt;span class="c1"&gt;# the midpoint, then we've exhausted either a1 or a2. Add enough&lt;/span&gt;
    &lt;span class="c1"&gt;# elements to reach the midpoint.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@merged&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nv"&gt;$mid&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$toMidPoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$mid&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;@merged&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;   &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@a1&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@merged&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;@a1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$toMidPoint&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;         &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@merged&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;@a2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$toMidPoint&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$isOdd&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$merged&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$merged&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$merged&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$mid&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Task Comparison
&lt;/h3&gt;

&lt;p&gt;Are any of these significantly more efficient? Here's a benchmark result for the median of two 100-element arrays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          Rate descr merge basic   diy
descr  38567/s    --  -49%  -54%  -83%
merge  75269/s   95%    --  -10%  -66%
basic  83832/s  117%   11%    --  -62%
diy   222222/s  476%  195%  165%    --
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although I would have thought the merge would be quite good, the fastest solution appears to be the do-it-yourself sort. This is probably because, even though it starts with a sort, the underlying algorithm is merge sort. Because the individual arrays are already sorted, the merge sort will converge quickly, and in optimized compiled code instead of interpreted Perl.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-391/#TASK2" rel="noopener noreferrer"&gt;Task 2: Arrange Boxes&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Task Description
&lt;/h3&gt;

&lt;p&gt;You are given an array of box dimensions. Write a script to determine the maximum number of these boxes that can fit inside each other in a single stack. For a box to fit inside another, it must be smaller in both dimensions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;@boxes = ([1, 3], [3, 5], [6, 8], [2, 4])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;4&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Sort by width ascending: &lt;code&gt;([1, 3], [2, 4], [3, 5], [6, 8])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Extract heights: [3, 4, 5, 8]&lt;/li&gt;
&lt;li&gt;[1, 3] -&amp;gt; [2, 4] -&amp;gt; [3, 5] -&amp;gt; [6, 8]&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;a class="mentioned-user" href="https://dev.to/boxes"&gt;@boxes&lt;/a&gt; = &lt;code&gt;([4, 5], [4, 6], [6, 7], [2, 3], [4, 3])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Sort by width ascending: &lt;code&gt;([2, 3], [4, 6], [4, 5], [4, 3], [6, 7])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Extract heights: (3, 6, 5, 3, 7)&lt;/li&gt;
&lt;li&gt;[2, 3] -&amp;gt; [4, 5] -&amp;gt; [6, 7]&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 3:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;a class="mentioned-user" href="https://dev.to/boxes"&gt;@boxes&lt;/a&gt; = &lt;code&gt;([5, 5], [5, 5], [5, 5])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Sort by width ascending: &lt;code&gt;([5, 5], [5, 5], [5, 5])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Extract heights: (5, 5, 5)&lt;/li&gt;
&lt;li&gt;[5, 5]&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 4:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;a class="mentioned-user" href="https://dev.to/boxes"&gt;@boxes&lt;/a&gt; = &lt;code&gt;([2, 100], [3, 200], [4, 300], [5, 50], [5, 400])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;4&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Sort by width ascending: &lt;code&gt;([2, 100], [3, 200], [4, 300], [5, 400], [5, 50])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Extract heights: (100, 200, 300, 400, 50)&lt;/li&gt;
&lt;li&gt;[2, 100] -&amp;gt; [3, 200] -&amp;gt; [4, 300] -&amp;gt; [5, 400]&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 5:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;a class="mentioned-user" href="https://dev.to/boxes"&gt;@boxes&lt;/a&gt; = &lt;code&gt;([10, 20], [15, 10], [20, 30], [12, 18], [16, 25])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Sort by width ascending: &lt;code&gt;([10, 20], [12, 18], [15, 10], [16, 25], [20, 30])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Extract heights: (20, 18, 10, 25, 30)&lt;/li&gt;
&lt;li&gt;[15, 10] -&amp;gt; [16, 25] -&amp;gt; [20, 30]&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Task Solution
&lt;/h3&gt;

&lt;p&gt;The examples hint very strongly that sorting by width and height could solve the problem, and indeed, for the examples, it does. I can't convince myself that my stacks won't be thwarted by long skinny boxes that sort into an inconvenient position. So I'm going to treat it as another search problem.&lt;/p&gt;

&lt;p&gt;The task doesn't mention the possibilities of rotating boxes, nor of putting small boxes side-by-side in bigger boxes. So I'm not going to consider those possibilities.&lt;/p&gt;

&lt;h4&gt;
  
  
  Side Quest: A Box Class
&lt;/h4&gt;

&lt;p&gt;I'm going to develop a small class around boxes, instead of depending on the convention of indexes 0 and 1 for width and height. It will add some readability to whether one box can be contained in another.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;feature&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt; &lt;span class="nb"&gt;no&lt;/span&gt; &lt;span class="nv"&gt;warnings&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;experimental::class&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;

&lt;span class="nv"&gt;class&lt;/span&gt; &lt;span class="nv"&gt;Box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;field&lt;/span&gt; &lt;span class="nv"&gt;$w&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;field&lt;/span&gt; &lt;span class="nv"&gt;$h&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[&lt;/span&gt;&lt;span class="si"&gt;$w&lt;/span&gt;&lt;span class="s2"&gt; x &lt;/span&gt;&lt;span class="si"&gt;$h&lt;/span&gt;&lt;span class="s2"&gt;]&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;overload&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;""&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nv"&gt;method&lt;/span&gt; &lt;span class="nv"&gt;canHold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;w&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$w&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I'm using Perl 5.44, so the class feature is available, but experimental. I don't want to see those warnings, thanks anyway.&lt;/li&gt;
&lt;li&gt;The constructor will get &lt;code&gt;height&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt; parameters, and the &lt;code&gt;:reader&lt;/code&gt; attribute will create accessors.&lt;/li&gt;
&lt;li&gt;For convenience in debugging, I want to be able to print a &lt;code&gt;Box&lt;/code&gt; object easily. Overloading the string ("") operator will make a textual representation of the object whenever I interpolate a &lt;code&gt;Box&lt;/code&gt; object reference in a string.&lt;/li&gt;
&lt;li&gt;The most important method I need is to test whether one &lt;code&gt;Box&lt;/code&gt; can contain another.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  The Main Quest
&lt;/h4&gt;

&lt;p&gt;Similar to last week, there'll be queue of possibilities to look at, and we'll try to extend each stack as far as we can.&lt;/p&gt;

&lt;p&gt;I'll work from the outside in, starting with the biggest containers, and considering all the rest that might fit inside.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="nf"&gt;boxes&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nv"&gt;@boxes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Turn given size pairs into Box objects.&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@boxes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$biggest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Set up a todo list, where each item contains&lt;/span&gt;
    &lt;span class="c1"&gt;# the stack so far, and the possible boxes that&lt;/span&gt;
    &lt;span class="c1"&gt;# could still fit inside. To begin, any box can&lt;/span&gt;
    &lt;span class="c1"&gt;# potentially be the biggest container.&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@box&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$stack&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;# The outside container&lt;/span&gt;
        &lt;span class="c1"&gt;# Choose boxes that could fit inside&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;canHold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@box&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Process the todo list, FIFO breadth-first&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="nv"&gt;@todo&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;$biggest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@$stack&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@$stack&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$biggest&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;# We can stop working on this stack if there&lt;/span&gt;
        &lt;span class="c1"&gt;# aren't enough boxes to improve on biggest&lt;/span&gt;
        &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@$available&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;@$stack&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;@$available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nv"&gt;$biggest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$nextSmallerBox&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@todo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$stack&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$nextSmallerBox&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
                        &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$nextSmallerBox&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;canHold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
                        &lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$biggest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
    <item>
      <title>PWC 390 Weird Ways to Wrangle Words</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Wed, 09 Sep 2026 15:06:01 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-390-weird-ways-to-wrangle-words-49mh</link>
      <guid>https://dev.to/boblied/pwc-390-weird-ways-to-wrangle-words-49mh</guid>
      <description>&lt;p&gt;Episode 390 of &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt; brings us a couple of tasks that turned out to be less code than I first thought. Let's put on some mood music and have a look. How about Sarah McLachlan's 1997 album, &lt;a href="https://www.youtube.com/playlist?list=PLMk7E7fNBrUSfmQLtGDoc2_hDMDXIa4U6" rel="noopener noreferrer"&gt;&lt;em&gt;Surfacing&lt;/em&gt;&lt;/a&gt;, where the first song is titled "Building a Mystery" -- appropriate for a task about decoding.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-390/#TASK1" rel="noopener noreferrer"&gt;Task 1: Decode String&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Task Description
&lt;/h3&gt;

&lt;p&gt;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 &amp;gt; 0 times.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example 1:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "2[3[a]]"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"aaaaaa"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;3[a]    =&amp;gt; aaa&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;2[3[a]] =&amp;gt; aaa aaa&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 2:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "10[a]"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"aaaaaaaaaa"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 3:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "a2[b]c3[d]e"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"abbcddde"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 4:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "2[a2[b]c]"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"abbcabbc"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 5:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "1[a]2[b3[c]]"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"abcccbccc"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Task Analysis
&lt;/h3&gt;

&lt;p&gt;At first glance, this looked like it was going to involve parsing balanced sets of nested brackets, which would mean some kind of stack structure, or maybe a simple recursive descent parser. It might be an opportunity to apply Perl modules that help with extracting balanced bracket groups; &lt;a href="https://metacpan.org/pod/Text::Balanced" rel="noopener noreferrer"&gt;Text::Balanced&lt;/a&gt; for example.&lt;/p&gt;

&lt;p&gt;However, backing off the keyboard for a moment, I noticed that there is a fundamental unit in the encoding. To repeat a constant string, the form is &lt;em&gt;N&lt;/em&gt;[&lt;em&gt;s&lt;/em&gt;]. This means to repeat the string &lt;em&gt;s&lt;/em&gt; for &lt;em&gt;N&lt;/em&gt; times. Perl has a replication operator, &lt;code&gt;$s x $N&lt;/code&gt;, which also means to repeat a string &lt;code&gt;$s&lt;/code&gt; for &lt;code&gt;$N&lt;/code&gt; times.&lt;/p&gt;

&lt;p&gt;A textual transformation can turn a fundamental group into a bit of equivalent Perl code. Execute the bit of code and that string is decoded.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# "3[a]" ==&amp;gt; eval { 'a' x 3 } ==&amp;gt; 'aaa'&lt;/span&gt;
&lt;span class="sr"&gt;s/ (\d+) \[ ( [^[\]]+) \] /$2 x $1/x&lt;/span&gt;&lt;span class="nv"&gt;eg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some regular expression deep cuts here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/x&lt;/code&gt; -- this flag allows me to add some white space into the regular expression for readability. You are free to judge just how much readability was accomplished.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(\d+)&lt;/code&gt; -- captures a group of digits as &lt;code&gt;$1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;\[&lt;/code&gt; and &lt;code&gt;\[&lt;/code&gt; -- the brackets would be meta-characters, so they need to be escaped to match literally.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[^[\]]+&lt;/code&gt; -- matches any character that is not a bracket. This will be captured into &lt;code&gt;$2&lt;/code&gt;. Note that I can't just move forward over everything that's not a ']' -- it would fail for strings like Example 1 (&lt;code&gt;"2[3[a]]"&lt;/code&gt;), because it would match &lt;code&gt;"3[a"&lt;/code&gt; after the &lt;code&gt;"2["&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/e&lt;/code&gt; - this flag executes the code in the substitution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When this substitution is applied, it eliminates a level of brackets. If we keep doing that until there are no brackets left, then we will have decoded the entire string. The task reduces to a one-liner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$str&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/ (\d+) \[ ( [^[\]]+ ) \] /$2 x $1/gx&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-390/#TASK2" rel="noopener noreferrer"&gt;Task 2: Order Characters&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Task Description
&lt;/h3&gt;

&lt;p&gt;You are given a string &lt;code&gt;$s&lt;/code&gt; (containing only alphabetic characters) and an integer &lt;code&gt;$k&lt;/code&gt; &amp;gt; 0. Write a script to choose one of the first &lt;code&gt;$k&lt;/code&gt; letters of the 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.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "dbca", $k = 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"adbc"&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Move 1: "bcad"&lt;/li&gt;
&lt;li&gt;Move 2: "cadb"&lt;/li&gt;
&lt;li&gt;Move 3: "adbc"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "geeks", $k = 2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"eegks"&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;First 2 letters: "g", "e"&lt;/li&gt;
&lt;li&gt;Move 1: "gekse" (move second letter "e")&lt;/li&gt;
&lt;li&gt;Move 2: "gksee" (move second letter "e")&lt;/li&gt;
&lt;li&gt;Move 3: "kseeg" (move first letter "g")&lt;/li&gt;
&lt;li&gt;Move 4: "seegk" (move first letter "k")&lt;/li&gt;
&lt;li&gt;Move 5: "eegks" (move first letter "s")&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 3:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "cbaed", $k = 3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"abcde"&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;First 3 letters: "c", "b", "a"&lt;/li&gt;
&lt;li&gt;Move 1: "cbeda"  (move "a")&lt;/li&gt;
&lt;li&gt;Move 2: "cedab"  (move "b")&lt;/li&gt;
&lt;li&gt;Move 3: "edabc"  (move "c")&lt;/li&gt;
&lt;li&gt;Move 4: "eabcd"  (move "d")&lt;/li&gt;
&lt;li&gt;Move 5: "abcde"  (move "e")&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 4:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "fedcba", $k = 4&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"abcdef"&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;First 4 letters: "f", "e", "d", "c"&lt;/li&gt;
&lt;li&gt;Move 1: "fdcbae" (move "e")&lt;/li&gt;
&lt;li&gt;Move 2: "dcbaef" (move "f")&lt;/li&gt;
&lt;li&gt;Move 3: "dcbefa" (move "a")&lt;/li&gt;
&lt;li&gt;Move 4: "dcefab" (move "b")&lt;/li&gt;
&lt;li&gt;Move 5: "defabc" (move "c")&lt;/li&gt;
&lt;li&gt;Move 6: "efabcd" (move "d")&lt;/li&gt;
&lt;li&gt;Move 7: "fabcde" (move "e")&lt;/li&gt;
&lt;li&gt;Move 8: "abcdef" (move "f")&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 5:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "perl", $k = 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"erlp"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 6:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "oloolooo", $k = 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"looloooo"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 7:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "oloooolo", $k = 1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"looloooo"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Task Analysis
&lt;/h3&gt;

&lt;p&gt;At first glance, the randomness of choosing one of &lt;code&gt;$k&lt;/code&gt; positions seems to make this a difficult problem. However, what we really have here is a search problem over all possible moves. Which, OK, still potentially a hard problem.&lt;/p&gt;

&lt;p&gt;From the start word, we have &lt;code&gt;$k&lt;/code&gt; new words that could be generated, and from each of those, &lt;code&gt;$k&lt;/code&gt; more. Clearly this could blow up if &lt;code&gt;$k&lt;/code&gt; is more than a small integer, but I don't see any way to take shortcuts, so exhaustive search it is.&lt;/p&gt;

&lt;p&gt;Searches are often presented or taught as recursive algorithms, but recursion is really just a way of hiding a stack. Searching requires two data structures: a stack or queue to hold the possibilities we haven't checked yet, and a lookup table to record things we have checked, so we don't get stuck in a loop.&lt;/p&gt;

&lt;h4&gt;
  
  
  Side Quest
&lt;/h4&gt;

&lt;p&gt;I'll want a convenient way to transform a word. Given a value of &lt;code&gt;$k&lt;/code&gt;, it should return the string with the &lt;em&gt;k&lt;/em&gt;'th letter moved to the end of the string. I'm going to do it by combining the substring before &lt;em&gt;k&lt;/em&gt;, the substring after &lt;em&gt;k&lt;/em&gt;, and then &lt;em&gt;k&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;s&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;k&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That feels like a lot of string operations. If we wanted to be too clever by half (and who doesn't), we could go into the fine print of the &lt;code&gt;substr&lt;/code&gt; function and read about the optional fourth argument, which replaces a piece of the string and returns what was there before. Armed with that dangerous piece of knowledge, we could write magic that erases letter &lt;em&gt;k&lt;/em&gt; and makes it reappear at the end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;move&lt;/span&gt;&lt;span class="p"&gt;($s, $k) {&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt; &lt;span class="o"&gt;.=&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'');&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The search is on
&lt;/h4&gt;

&lt;p&gt;For the search itself, I'll prime the pump by putting the first set of moves onto the stack, then processing the stack until it's empty. As we take a word off the stack, we'll ignore it if it's a word we've already processed. Otherwise, check if it's the best yet, and then generate a new set of &lt;code&gt;$k&lt;/code&gt; moves for the stack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;k&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;k out of range&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$best&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;z&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nb"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%seen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@stack&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;pop&lt;/span&gt; &lt;span class="nv"&gt;@stack&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$seen&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nv"&gt;$seen&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;$best&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="ow"&gt;lt&lt;/span&gt; &lt;span class="nv"&gt;$best&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$best&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can push multiple items onto the end of an array in one statement. Instead of a &lt;code&gt;for&lt;/code&gt; loop, I'm using &lt;code&gt;map&lt;/code&gt; to make a list of the &lt;code&gt;$k&lt;/code&gt; moves.&lt;/li&gt;
&lt;li&gt;Lexicographic comparison uses the &lt;code&gt;lt&lt;/code&gt; operator instead of &lt;code&gt;&amp;lt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I'm using &lt;code&gt;pop&lt;/code&gt; to process the stack, which makes it a depth-first search. If I used &lt;code&gt;shift&lt;/code&gt;, it would be a breadth-first search (and the stack would act like a queue). Since we have to look at every possible word, it doesn't much matter which we use.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  But wait, there's more
&lt;/h3&gt;

&lt;p&gt;This solution doesn't record the set of moves that got to the result. If I needed that, the stack would contain records of two things: the word to be processed, and a reference to a list of words. The initial stack for Example 3 would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;["&lt;/span&gt;&lt;span class="s2"&gt;baedc&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;["&lt;/span&gt;&lt;span class="s2"&gt;cbaed&lt;/span&gt;&lt;span class="p"&gt;"]&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;    &lt;span class="c1"&gt;# move("cbaed", 1)&lt;/span&gt;
  &lt;span class="p"&gt;["&lt;/span&gt;&lt;span class="s2"&gt;caedb&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;["&lt;/span&gt;&lt;span class="s2"&gt;cbaed&lt;/span&gt;&lt;span class="p"&gt;"]&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;    &lt;span class="c1"&gt;# move("cbaed", 2)&lt;/span&gt;
  &lt;span class="p"&gt;["&lt;/span&gt;&lt;span class="s2"&gt;cbeda&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="p"&gt;["&lt;/span&gt;&lt;span class="s2"&gt;cbaed&lt;/span&gt;&lt;span class="p"&gt;"]&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# move("cbaed", 3)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Processing the stack would involve unpacking this structure, and growing the list of words that got us here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;pop&lt;/span&gt; &lt;span class="nv"&gt;@stack&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$howWeGotHere&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$seen&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nv"&gt;$seen&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@$howWeGotHere&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get this information out of the function, we would need to remember not only the best word, but also the path that reached it. We would then return either a pair of values in a list, or return multiple values. Returning multiple values stumbles into the swamp of array versus scalar context, so I prefer to return a single reference to a pair of things.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$best&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;z&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nb"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$bestPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$str&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="ow"&gt;lt&lt;/span&gt; &lt;span class="nv"&gt;$best&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$best&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$bestPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$howWeGotHere&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$best&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$bestPath&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
    <item>
      <title>PWC 388 Dyck Words: I Refuse to Indulge in the Obvious Jokes</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Sun, 30 Aug 2026 23:00:20 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-388-dyck-words-i-refuse-to-indulge-in-the-obvious-jokes-56i2</link>
      <guid>https://dev.to/boblied/pwc-388-dyck-words-i-refuse-to-indulge-in-the-obvious-jokes-56i2</guid>
      <description>&lt;p&gt;As soon as I saw the title of this week's challenge, I had to run to Google. As a person with a German surname that is sometimes mispronounced for sophomoric humor, I did not want to fall into that trap. Sure enough, that name is pronounced "deek", so let's restrain ourselves, shall we?&lt;/p&gt;

&lt;p&gt;On the other hand, as a person with the emotional maturity of a fourteen-year-old, I am well aware of the &lt;a href="https://www.youtube.com/playlist?list=PLELfhTnLnUSZpjrZJo61p6QZXwM7aNuGy" rel="noopener noreferrer"&gt;Letterkenny Dycks&lt;/a&gt;. So, take a moment and I'll meet you back here.&lt;/p&gt;

&lt;p&gt;Now that we have that out of our system, let's begin.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-388/#TASK1" rel="noopener noreferrer"&gt;Task 1:: Dyck Words&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A Dyck Word of order &lt;em&gt;n&lt;/em&gt; is a string of length &lt;em&gt;2n&lt;/em&gt; consisting of &lt;em&gt;n&lt;/em&gt; ‘U’ (Up) characters and &lt;em&gt;n&lt;/em&gt; ‘D’ (Down) characters such that no initial prefix of the string contains more ‘D’s than ‘U’s.&lt;/p&gt;

&lt;p&gt;Write a script to return a list of all valid Dyck words of length &lt;em&gt;2n&lt;/em&gt;, sorted in lexicographical (alphabetical) order.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt; _Input: &lt;code&gt;$n = 1&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;("UD")&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$n = 2&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;("UDUD","UUDD")&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 3:&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$n = 3&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;("UDUDUD", "UDUUDD", "UUDDUD", "UUDUDD", "UUUDDD")&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 4:&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$n = 0&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;("")&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 5:&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$n = 4&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;("UDUDUDUD", "UDUDUUDD", "UDUUDDUD", "UDUUDUDD", "UDUUUDDD", "UUDDUDUD", "UUDDUUDD", "UUDUDDUD", "UUDUDUDD", "UUDUUDDD","UUUDDDUD", "UUUDDUDD", "UUUDUDDD", "UUUUDDDD")&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Discussion
&lt;/h2&gt;

&lt;p&gt;This pattern can be visualized as walking along a grid, starting at (0,0), staying entirely inside the wedge between 0° and 45°, and ending back on the &lt;em&gt;x&lt;/em&gt; axis. If you replace 'U' and 'D' with '(' and ')', it represents strings with balanced parentheses.&lt;/p&gt;

&lt;p&gt;Generating these strings is going to be some kind of recursive algorithm. While checking on the pronunciation of "Dyck", I stumbled on a CPAN module, &lt;a href="https://metacpan.org/pod/Math::DyckWords" rel="noopener noreferrer"&gt;Math::DyckWords&lt;/a&gt;, that implements these strings. Peeking at the source code, sure enough there's a recursive algorithm. Just like AI, I'm going to train myself by scanning a public web site, regurgitating something similar, taking credit for it, and skimming over the ethical implications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Working top-down, I'm going to assume that there's a function that can return a list of appropriate strings. I'll handle the special case of 0, and turn the list into the sorted set that the problem specifies. Because of the way the recursion works, and because we've chosen to use the letters U and D, it turns out that the list comes back in reverse alphabetical order, so we can avoid sorting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;generateDyck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[""];&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;reverse&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On to the meat of the problem. My recursive function will have a signature that reflects how deep into the string we've come.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;generateDyck&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;dyck&lt;/span&gt;&lt;span class="err"&gt;=[],&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;word&lt;/span&gt;&lt;span class="err"&gt;='&lt;/span&gt;&lt;span class="nf"&gt;U&lt;/span&gt;&lt;span class="err"&gt;',&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;nU&lt;/span&gt;&lt;span class="err"&gt;=1,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;nD&lt;/span&gt;&lt;span class="err"&gt;=0,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;depth&lt;/span&gt;&lt;span class="err"&gt;=1)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm making generous use of default values for parameters. The first call from &lt;code&gt;task()&lt;/code&gt; is just &lt;code&gt;generateDyck($n)&lt;/code&gt;, so all the rest of the parameters will get their values from the signature.  The list of words will accumulate in the &lt;code&gt;$dyck&lt;/code&gt; array. The word we're currently working on is in &lt;code&gt;$word&lt;/code&gt;. Our first character is always a 'U', and the counts reflect that. The &lt;code&gt;$depth&lt;/code&gt; parameter is the depth of the recursion; it's not really necessary but helps in debugging.&lt;/p&gt;

&lt;p&gt;To build the string, we add a letter at a time, preferring 'U' first. The number of D's can never get ahead of the number of U's. Eventually we return the reference to the list of words; the return value is only really used at the top-level call.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# We have space to add both a U and a D&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$nU&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$nD&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$nU&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$nD&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# U goes before D&lt;/span&gt;
        &lt;span class="nv"&gt;generateDyck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$dyck&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;U&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;$nU&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$nD&lt;/span&gt;     &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$depth&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;generateDyck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$dyck&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;D&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;$nU&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="nv"&gt;$nD&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$depth&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# We have space, but a U must be next&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$nU&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$nD&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$nU&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$nD&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
         &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$nU&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$nD&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;generateDyck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$dyck&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;U&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nv"&gt;$nU&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$nD&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$depth&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$nU&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# We have all the Us, must add enough D to balance.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$nD&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$need&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$nD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nv"&gt;generateDyck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$dyck&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;D&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="nv"&gt;$need&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$nU&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$nD&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$need&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$depth&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="c1"&gt;# $nD == $n&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;# We have n of each, so save a complete word.&lt;/span&gt;
            &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@$dyck&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$dyck&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
    <item>
      <title>PWC 386 All Your Base Are Belong to Rational Numbers</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Fri, 14 Aug 2026 16:41:36 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-386-all-your-base-are-belong-to-rational-numbers-g88</link>
      <guid>https://dev.to/boblied/pwc-386-all-your-base-are-belong-to-rational-numbers-g88</guid>
      <description>&lt;p&gt;We have a couple of math problems for &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-386/" rel="noopener noreferrer"&gt;this week's challenge tasks&lt;/a&gt;. Let's set the mood with Paul Simon's song, &lt;a href="https://www.youtube.com/watch?v=UzHZl9J9AK4" rel="noopener noreferrer"&gt;"When Numbers Get Serious"&lt;/a&gt;, from the under-rated 1983 album, &lt;em&gt;Hearts and Bones&lt;/em&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-386/#TASK1" rel="noopener noreferrer"&gt;Task 1: Reverse Base&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Task Description
&lt;/h3&gt;

&lt;p&gt;You are given a string representing a number, and an integer specifying the base of that representation.&lt;/p&gt;

&lt;p&gt;Write a function to convert this string to an integer. (For bases greater than 10, use characters A-Z, a-z, + and / in that order.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example 1&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; $num = "101010", $base = 2 &lt;em&gt;Output:&lt;/em&gt; 42&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 2&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; $num = "EEADEE", $base = 16 &lt;em&gt;Output:&lt;/em&gt; 15642094&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 3&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; $num = "755", $base = 8 &lt;em&gt;Output:&lt;/em&gt; 493&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 4&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; $num = "1BRJB", $base = 36 &lt;em&gt;Output:&lt;/em&gt; 2228519&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 5&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; $num = "7MyqL", $base = 64 &lt;em&gt;Output:&lt;/em&gt; 123456789&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;p&gt;This is the inverse of last week's problem. We need a table that looks up the values of the symbols, and a loop that multiplies each digit to its exponent place in the number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;num&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;base&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;%VALUE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;9&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;z&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="p"&gt;');&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$place&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'')&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;ne&lt;/span&gt; &lt;span class="p"&gt;''&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;$place&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$VALUE&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$d&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="nv"&gt;$place&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="nv"&gt;$base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The %VALUE hash is created once (use of &lt;code&gt;state&lt;/code&gt; variable).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;do&lt;/code&gt; statement lets me localize the index variable, &lt;code&gt;$v&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We loop by taking the last character from &lt;code&gt;$str&lt;/code&gt; each time. There are a couple of trivial variations:

&lt;ul&gt;
&lt;li&gt;We could split the string into individual characters and &lt;code&gt;pop&lt;/code&gt; characters&lt;/li&gt;
&lt;li&gt;We could reverse the string and loop forwards instead.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-386/#TASK2" rel="noopener noreferrer"&gt;Task 2: Rational Numbers&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Task Description
&lt;/h3&gt;

&lt;p&gt;You are given two strings representing non-negative rational numbers. Write a script to return true if the two given rational numbers are same otherwise false.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example 1:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; $rat1 = &lt;code&gt;"0.(12)"&lt;/code&gt; $rat2 = &lt;code&gt;"0.(121)"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Expansion of &lt;code&gt;"0.(12)"  = 0.12121212...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Expansion of &lt;code&gt;"0.(121)" = 0.121121121...&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 2:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; $rat1 = &lt;code&gt;"0.1(23)"&lt;/code&gt; $rat2 = &lt;code&gt;"0.12(32)"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Expansion of &lt;code&gt;"0.1(23)"  = 0.1232323...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Expansion of &lt;code&gt;"0.12(32)" = 0.12323232...&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 3"&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; $rat1 = &lt;code&gt;"0.1(234)"&lt;/code&gt; $rat2 = &lt;code&gt;"0.12(342)"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; true&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 4:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; $rat1 = &lt;code&gt;"12.99(99)"&lt;/code&gt; &lt;code&gt;$rat2 = "13."&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example 5:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; $rat1 = &lt;code&gt;"0.(123)"&lt;/code&gt;  $rat2 = &lt;code&gt;"0.1(231)"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;true&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Observations
&lt;/h3&gt;

&lt;p&gt;There's a temptation to do something with string manipulation to see if &lt;code&gt;$rat1&lt;/code&gt; can be converted to &lt;code&gt;$rat2&lt;/code&gt;, but Example 4 trips that up. What this requires is to think back to middle-school math and recall how to convert a repeating decimal to the form of a rational number with a numerator and denominator.&lt;/p&gt;

&lt;p&gt;If we convert both &lt;code&gt;rat1&lt;/code&gt; and &lt;code&gt;rat2&lt;/code&gt; into the form of rational numbers we can compare them.&lt;/p&gt;

&lt;p&gt;So how do we convert decimal representation to a rational number? The trick is to multiply the number by enough powers of 10 so that all the fixed parts are left of the decimal, and the repeating part starts at the decimal. Then subtract away the repeating decimals to leave a simple division.&lt;/p&gt;

&lt;p&gt;For example, let's take example 4, 12.(99). Let &lt;em&gt;s&lt;/em&gt;=12.(99). Then, &lt;em&gt;100s&lt;/em&gt; = 1299.(99).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   100s = 1299.9999...
   -  s =   12.9999...
   -------------------
    99s = 1287.0

    s = 1287/99 = 13/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In general, we'll have to identify the fixed and repeating parts, then use their lengths to set up multipliers to shift the decimal point.&lt;/p&gt;

&lt;p&gt;Perl has modules for doing arithmetic with rational numbers. The most convenient is &lt;a href="https://perldoc.perl.org/bigrat" rel="noopener noreferrer"&gt;&lt;code&gt;bigrat&lt;/code&gt;&lt;/a&gt;. It has some nice properties. First, it's a core module, so it's always present without an external dependency. Second, it reduces fractions to their lowest-common-denominator form (e.g., &lt;code&gt;1/2&lt;/code&gt; compares equal to &lt;code&gt;2/4&lt;/code&gt;), so we don't have to worry about that. And, third, it overloads the common arithmetic operators, including &lt;code&gt;==&lt;/code&gt; comparison.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;If we assume we can create a rational number from the odd representation given as input (let's defer that assumption into a function called &lt;code&gt;asRational()&lt;/code&gt;), then the main task is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;bigrat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;rat1&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;rat2&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;asRational&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$rat1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;asRational&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$rat2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$r1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$r2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the remaining problem is to write &lt;code&gt;asRational()&lt;/code&gt;. It needs to extract the fixed and repeating parts, which can be done with a regular expression. Then it needs to figure out the multipliers needed, based on the lengths of the strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;asRational&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;rat&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$whole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$fixed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$repeat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$rat&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;m/
            (\d*)       # Capture whole number part before decimal
            \.          # Decimal point always present
            (\d*)?      # Capture optional fixed digits
            (?:\(       # Group the part in parentheses
            (\d+)       # Capture repeating digits
            \))?        # Close parentheses group, repeat is optional
            /x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$fixed&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$repeat&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Multiplier to move fixed to right of decimal point.&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$multFixed&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$fixed&lt;/span&gt;  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nb"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fixed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;# Multiplier to move repeat to right of decimal point, minus 1&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$multRepeat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$repeat&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nb"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$repeat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;# Move all digits right of decimal point. Example: 1.2(34) --&amp;gt; 1234.&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$numerator&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$whole&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$multFixed&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$fixed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$multRepeat&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$repeat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$denominator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$multFixed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;$multRepeat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Returns a BigRat object, not math. Handles reducing fractions.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$numerator&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;$denominator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both the &lt;code&gt;fixed&lt;/code&gt; and &lt;code&gt;repeat&lt;/code&gt; parts are optional. If they're not picked up by the regular expression match, set them to zero so that they disappear in the later arithmetic (as opposed to causing exception for using an undefined value).&lt;/li&gt;
&lt;li&gt;Similarly, for the multipliers, use 1 if not present, otherwise the '0' would be a string of length 1 and cause the  multiplier to be 10.&lt;/li&gt;
&lt;li&gt;The rest is math, except that the &lt;code&gt;/&lt;/code&gt; opertor is overridden by the &lt;code&gt;bigrat&lt;/code&gt; module.  It no longer does division; it constructs a &lt;code&gt;Math::BigRat&lt;/code&gt; object representing a rational number with a numerator and a denominator.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
    <item>
      <title>PWC 382 Replace Question Marks</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Wed, 15 Jul 2026 17:00:51 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-382-replace-question-marks-3enn</link>
      <guid>https://dev.to/boblied/pwc-382-replace-question-marks-3enn</guid>
      <description>&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-382/#TASK2" rel="noopener noreferrer"&gt;Task 2: Replace Question Mark&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You are given a string that contains only 0, 1 and ? characters.&lt;/p&gt;

&lt;p&gt;Write a script to generate all possible combinations when replacing the question marks with a zero or one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt; &lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "01??0"&lt;/code&gt;&lt;br&gt;
&lt;em&gt;Output:&lt;/em&gt; ("01000", "01010", "01100", "01110")&lt;/p&gt;
&lt;h2&gt;
  
  
  Cogitation
&lt;/h2&gt;

&lt;p&gt;The "?" reminds me of shell file name expansion. In &lt;em&gt;bash&lt;/em&gt; and similar shells, a question mark acts as a wild card, and there is also the expansion that a group in braces expands to all combinations of the things in braces. For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"a{01}b"&lt;/span&gt;
&lt;span class="go"&gt;a0b a1b
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perl can do the same trick with the &lt;code&gt;glob&lt;/code&gt; function, performing the expansion into a list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;a{0,1}b&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So a one-liner solution converts every '?' into the string "{0,1}" and then applies &lt;code&gt;glob&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;perl&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;wE&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;say join " ", glob($ARGV[0] =~ s/\?/{0,1}/gr )&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a?c&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;a0ca1c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More fun would be to process the substitution. Create a queue of possible strings, starting with the given string. Take the string from the head of the queue and replace it with two new strings that have a "0" and "1" in place of the question mark; put those strings at the end of the queue. If there are no question marks, then that's a final string that's part of the solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@replaced&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$str&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt; &lt;span class="nv"&gt;@queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;?&lt;/span&gt;&lt;span class="p"&gt;')&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/\?/0/r&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/\?/1/r&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@replaced&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;@replaced&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I like to use &lt;code&gt;index&lt;/code&gt; instead of regular expression match when I can, because it's (probably) more efficient.&lt;/li&gt;
&lt;li&gt;Multiple things can be &lt;code&gt;push&lt;/code&gt;ed onto a list in one statement.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
    <item>
      <title>PWC 382 Hamiltonian Cycle</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Wed, 15 Jul 2026 02:08:26 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-382-hamiltonian-cycle-8no</link>
      <guid>https://dev.to/boblied/pwc-382-hamiltonian-cycle-8no</guid>
      <description>&lt;p&gt;It would be so easy to say that the musical selection for this week's challenges is the &lt;a href="https://www.youtube.com/watch?v=vvtCikwLdHs" rel="noopener noreferrer"&gt;Hamilton&lt;/a&gt; soundtrack, but what came to mind is that these are search problems, so I'm reaching back fifty years to Chicago and &lt;a href="https://www.youtube.com/watch?v=08sDz9Fqfnc" rel="noopener noreferrer"&gt;"(I've Been) Searchin' So Long"&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-382/#TASK1" rel="noopener noreferrer"&gt;Task 1: Hamiltonian Cycles&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You are given a target number. Write a script to arrange all the whole numbers from 1 up to the given target number into a circle so that every pair of side-by-side numbers adds up to a perfect square. Please make sure, the last number and the first must also add up to a square.&lt;/p&gt;

&lt;p&gt;Example: for &lt;em&gt;n&lt;/em&gt;=32, a cycle would be: 1, 8, 28, 21, 4, 32, 17, 19, 30, 6, 3, 13, 12, 24, 25, 11, 5, 31, 18, 7, 29, 20, 16, 9, 27, 22, 14, 2, 23, 26, 10, 15&lt;/p&gt;

&lt;h3&gt;
  
  
  Cogitation
&lt;/h3&gt;

&lt;p&gt;Imagine that the numbers 1 through &lt;em&gt;n&lt;/em&gt; are nodes in a graph. There's an edge from one node to another if their sum is a square (1 can go to 8 or 3 or 15, for example). The problem is to visit each node once in this graph, and end up back at the start node -- a Hamiltonian cycle. This is related to the traveling salesman problem, and is in the same NP-complete category of being potentially very difficult to solve in the general case. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fovjkrxkmr015zt017czm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fovjkrxkmr015zt017czm.png" alt="Graph of sums that add to squares when n=32" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of explicitly building a representation of this graph, I took the approach of a breadth-first search. Let's start with 1 (any starting point will do, since it's a cycle), and queue up all the subsequent numbers that would work (1,3, 1,8, 1,15, 1,24). Then, from the remaining numbers, let's branch out to the next possibilities (1,3,6, 1,3,12, 1,3,21, 1,8,7, etc.), and continue evaluating each growing sequence until it either gets back to the start or runs out of square sums.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;The first thing I need to know is which square numbers are in play. The largest sum we can form is &lt;code&gt;n+(n-1)&lt;/code&gt;, so I want a list of squares that are less than &lt;code&gt;2n-1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;@Square&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nv"&gt;*$n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My breadth-first search is going to build up a queue of possible sequences, and the remaining available numbers excluding what's in the sequence. The seed sequence is &lt;code&gt;[1]&lt;/code&gt;, with the numbers from 2 to &lt;em&gt;n&lt;/em&gt; available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@queue&lt;/code&gt; is a list of pairs; each member of the pair is a list.&lt;/p&gt;

&lt;p&gt;Now, while there are things in the queue, we want to try to extend each sequence with a number that adds up to a square. The basic structure of the loop will look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@cycle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;# There can be more than one&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@queue&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@$available&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;# Used up all the numbers, is it a cycle?&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;# End of the sequence&lt;/span&gt;
            &lt;span class="c1"&gt;# Extend the sequence if possible, or drop it&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;@cycle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we have a sequence that uses up all the numbers, we need to verify that it completes a cycle by adding the first and last numbers. If so, we can save the sequence as a possible return value. If not, oh well, we wasted time and we go on the next possibility in the queue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@$available&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@Square&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@cycle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first and last elements of the sequence are from indexes 0 and -1. I use &lt;code&gt;List::Util::any&lt;/code&gt; to check if that sum exists in &lt;code&gt;@Square&lt;/code&gt;, the short list of possible squares that we set up at the beginning.&lt;/p&gt;

&lt;p&gt;The other possibility is that we can try to extend the sequence. Given the last number from the sequence (call it &lt;code&gt;$j&lt;/code&gt;), we need to add a number to it to reach a square. The possibilities are all squares from &lt;code&gt;@Square&lt;/code&gt; that are greater then &lt;code&gt;$j&lt;/code&gt;. If those numbers are available, move the number from the &lt;code&gt;$available&lt;/code&gt; list to the &lt;code&gt;$sequence&lt;/code&gt; list, and then add that to the end of the queue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$sq&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$j&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@Square&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$sq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$which&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;first_index&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@avail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nv"&gt;$which&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$which&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="c1"&gt;#*];&lt;/span&gt;
        &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;@avail&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The end of the list is right there at index &lt;code&gt;[-1]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The only possible squares we might form are ones that are bigger then &lt;code&gt;$j&lt;/code&gt; and in the &lt;code&gt;@Square&lt;/code&gt; list we helpfully formed earlier, so let's only consider that short list.&lt;/li&gt;
&lt;li&gt;I'm using &lt;code&gt;List::MoreUtils::first_index&lt;/code&gt; to look up the number I need. It's a linear search but in a short list, so possible inefficiency doesn't bother me much.&lt;/li&gt;
&lt;li&gt;Having the index makes it possible to reduce my new available list by using an array slice to select the ranges before and after the element we want to delete.&lt;/li&gt;
&lt;li&gt;We can now push our new, longer sequence and our new, shorter available list to the end of the queue for consideration later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, finally all in one piece, this is what I have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;List::&lt;/span&gt;&lt;span class="nv"&gt;AllUtils&lt;/span&gt; &lt;span class="sx"&gt;qw/any first_index/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# All the squares that might be sums of the available numbers.&lt;/span&gt;
    &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;@Square&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nv"&gt;*$n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@cycle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@queue&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@$available&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@Square&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@cycle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$sq&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$j&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@Square&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$sq&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$j&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$which&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;first_index&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@avail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="nv"&gt;$which&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$which&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$available&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="c1"&gt;#*];&lt;/span&gt;
                &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$sequence&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$diff&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;@avail&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;@cycle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Surprise
&lt;/h3&gt;

&lt;p&gt;So, with all the pieces in place, I run the program and the answer doesn't match the example. It turns out that there are multiple possible Hamiltonian cycles (2 for n=32, 22 for n=34, and 115 for n=35).&lt;/p&gt;

</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
    <item>
      <title>PWC 376 Doubled Words</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Thu, 04 Jun 2026 14:18:08 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-376-doubled-words-7g3</link>
      <guid>https://dev.to/boblied/pwc-376-doubled-words-7g3</guid>
      <description>&lt;p&gt;There are two things that every Perl developer knows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parsing HTML with regular expressions is a bad idea.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;My&lt;/em&gt; situation is unique and exceptional, such that parsing HTML with regular expressions is ingenious and optimal.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's see the task. I think you know where this is going.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-376/#TASK2" rel="noopener noreferrer"&gt;Task 2: Double Words&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;You are given a string (which may contain embedded newlines) which is taken from a page on a website. The string will not contain brackets &lt;code&gt;[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Write a script that will find doubled words (such as “this this”) and highlight (wrap in brackets) each doubled word.&lt;/p&gt;

&lt;p&gt;The script should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Work across lines, even finding situations where a word at the end of one line is repeated at the beginning of the next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find doubled words despite capitalization differences, such as with 'The the...', as well as allow differing amounts of whitespace (spaces, tabs, newlines, and the like) to lie between the words.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find doubled words even when separated by HTML tags. For example, to make a word bold: '...it is &amp;lt;B&amp;gt;very&amp;lt;/B&amp;gt; very important...'.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only show lines containing doubled words.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adapted from &lt;a href="https://regex.info/book.html" rel="noopener noreferrer"&gt;&lt;em&gt;Mastering Regular Expressions&lt;/em&gt;, Third Edition, by Jeffrey E. F. Friedl&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Example 1&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "you're given the job of checking the pages on a\nweb server for doubled words (such as 'this this'), a common problem\nwith documents subject to heavy editing."&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"web server for doubled words (such as '[this] [this]'), a common problem"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Example 2&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "Find doubled words despite capitalization differences, such as with 'The\nthe...', as well as allow differing amounts of whitespace (spaces,\ntabs, newlines, and the like) to lie between the words."&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"Find doubled words despite capitalization differences, such as with '[The]\n[the]...', as well as allow differing amounts of whitespace (spaces,"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Example 3&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "to make a word bold: '...it is &amp;lt;B&amp;gt;very&amp;lt;/B&amp;gt; very important...'."&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"to make a word bold: '...it is &amp;lt;B&amp;gt;[very]&amp;lt;/B&amp;gt; [very] important...'."&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Example 4&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "Perl officially stands for Practical Extraction and Report Language, except when it doesn't."&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;""&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Example 5&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Input:&lt;/em&gt; &lt;code&gt;$str = "There's more than one one way to do it.\nEasy things should be easy and hard things should be possible."&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Output:&lt;/em&gt; &lt;code&gt;"There's more than [one] [one] way to do it."&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  So it begins
&lt;/h2&gt;

&lt;p&gt;The reference to &lt;em&gt;Mastering Regular Expressions&lt;/em&gt; seems like a pretty strong hint. Back when I was doing HTML and XML processing, I always favored using a module to parse tagged text (&lt;a href="https://metacpan.org/dist/XML-Twig" rel="noopener noreferrer"&gt;&lt;code&gt;XML::Twig&lt;/code&gt;&lt;/a&gt; was a particular favorite), but let's take the hint.&lt;/p&gt;

&lt;p&gt;A sort of obvious thing to do here is to split the string into words, but it's going to be annoying because of the possibility of HTML tags.  And once we break the string up, we'll lose the space and tags that we need to retain for the requested output.&lt;/p&gt;

&lt;p&gt;"The string will not contain brackets" is an odd thing to say. But it turns out to be useful, because we only want to print output lines that &lt;em&gt;do&lt;/em&gt; contain brackets, so this little clause is actually doing us a favor.&lt;/p&gt;

&lt;h2&gt;
  
  
  An outline
&lt;/h2&gt;

&lt;p&gt;Let's assume that we can conjure up a regular expression to use with &lt;code&gt;split&lt;/code&gt; to extract the words; let's call it &lt;code&gt;$sepRE&lt;/code&gt;. We can then compare consecutive pairs of words to find duplication. That solves half the problem, but loses the context in the original string. We need to reproduce the original text, plus highlighting brackets, including all the stuff between words.&lt;/p&gt;

&lt;p&gt;Because we have weird habits, we have (more than once) read through all the documentation of &lt;code&gt;split&lt;/code&gt;, and so we know that there is a variation in which the function can return both the desired substrings &lt;em&gt;and&lt;/em&gt; the separators. To wit, if we enclose the regular expression in parentheses, &lt;code&gt;split&lt;/code&gt; will return all the pieces of the string, alternating between separators and substrings. The first piece we need looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="sr"&gt;/($sepRE)/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the words will be in either the even or odd elements of &lt;code&gt;@word&lt;/code&gt;, depending on whether the string started with a separator. We can check for duplicates by skipping along in pairs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Take every other word. Skip over a leading separator.&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;m/$sepRE/&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$second&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nv"&gt;$#word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$second&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="nv"&gt;$w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/($w[0])/[$1]/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$second&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/($w[1])/[$1]/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;$first&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$second&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That marks up the duplicate words, but only in the &lt;code&gt;@word&lt;/code&gt; array. We need to face the problem of getting the desired output. To get there, put the &lt;code&gt;@word&lt;/code&gt; array back into a single string, and then &lt;code&gt;grep&lt;/code&gt; for the lines that contain our newly-inserted brackets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Reassemble the string, now with some words possibly bracketed&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$highlighted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="p"&gt;("",&lt;/span&gt; &lt;span class="nv"&gt;@word&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;# Output includes only lines where we inserted brackets&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt;
            &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="sr"&gt;/[\[\]]/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                 &lt;span class="nb"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\n/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$highlighted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A few minor details
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Case insensitivity. In our check for duplicates, we need to ignore case differences, so let's compare the lowercase versions of the words: &lt;code&gt;if ( lc($w[0]) eq lc($w[1]) )&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Punctuation. As shown in Example 2, punctuation surrounding the words should be ignored. Let's whip up a quick function to trim leading and trailing punctuation (the &lt;code&gt;[:punct:]&lt;/code&gt; character class is handy for this), and use it before we compare&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;trimPunct&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;word&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/^[[:punct:]]+//&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$word&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/[[:punct:]]+$//&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;trimPunct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="nv"&gt;trimPunct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$second&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  About that regular expression
&lt;/h2&gt;

&lt;p&gt;Time to take care of that regular expression that acts as the word separator. With some experimentation (the &lt;a href="https://regex101.com" rel="noopener noreferrer"&gt;regex101&lt;/a&gt; web site is good for that), we arrived at this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt; &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;$sepRE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
&lt;span class="sx"&gt;qr/ \s*     # Possible white space followed by
  (?:       # ( a group of a tag and more white space
   &amp;lt;[^&amp;gt;]*&amp;gt;  #  ... an HTML tag
   \s*      #  ... optional space
  )+        # ) there can be multiple tags
  | \s+     # Or just white space
/&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not too bad. Didn't even require look-around assertions.  Some notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;state $sepRE = qr/.../&lt;/code&gt; -- This is a constant regular expression, so we can use &lt;code&gt;state&lt;/code&gt; to only evaluate it once.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;qr//x&lt;/code&gt; -- The &lt;code&gt;x&lt;/code&gt; flag allows us to add formatting and comments to the expression &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(?:...)&lt;/code&gt; -- We want to group, but we don't need the overhead of capturing, so &lt;code&gt;(?:)&lt;/code&gt; is a non-capturing group.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;complicated | \s+&lt;/code&gt; -- Why is the complicated part first? Because the alternatives are evaluated left to right. If &lt;code&gt;\s+&lt;/code&gt; eats up the white space, the expression matches and wouldn't proceed to trying tags.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, here's the &lt;a href="https://github.com/boblied/perlweeklychallenge-club/blob/master/challenge-376/bob-lied/perl/ch-2.pl" rel="noopener noreferrer"&gt;whole thing&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;state&lt;/span&gt; &lt;span class="nv"&gt;$sepRE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;qr/ \s*     # Possible white space followed by
                     (?:       # ( a group of a tag and more white space
                      &amp;lt;[^&amp;gt;]*&amp;gt;  #  ... an HTML tag
                      \s*      #  ... optional space
                     )+        # ) There can be multiple tags
                     | \s+     # Or just white space
                   /&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Using () in RE includes separators in the array&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="sr"&gt;/($sepRE)/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;# Take every other word. Skip over a leading separator.&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;m/$sepRE/&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$second&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nv"&gt;$#word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;trimPunct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nv"&gt;trimPunct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$second&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;lc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="nb"&gt;lc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$w&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$first&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/($w[0])/[$1]/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nv"&gt;$word&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$second&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/($w[1])/[$1]/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nv"&gt;$first&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;$second&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Reassemble the string, now with some words possibly bracketed&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$highlighted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="p"&gt;("",&lt;/span&gt; &lt;span class="nv"&gt;@word&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;# Output includes only lines where we inserted brackets&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="sr"&gt;/[\[\]]/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\n/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$highlighted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the music for this week's challenge was &lt;a href="https://www.youtube.com/watch?v=dD-SpHH7qDA" rel="noopener noreferrer"&gt;Double Vision&lt;/a&gt; by Foreigner.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
    <item>
      <title>PWC 373 Task 2: Let's Dance to List Division</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Wed, 13 May 2026 23:22:28 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-373-task-2-lets-dance-to-list-division-1e0k</link>
      <guid>https://dev.to/boblied/pwc-373-task-2-lets-dance-to-list-division-1e0k</guid>
      <description>&lt;p&gt;The task title reminded me of the song &lt;a href="https://www.youtube.com/watch?v=ayuooyWPEUc" rel="noopener noreferrer"&gt;Let's Dance to Joy Division&lt;/a&gt;. Oddly applicable lyrics for a blog about programming: "But I worked something out last night that changed this little boy's brain, a small piece of advice that took 22 years in the make, and I will break it for you now. Please learn from my mistakes." And who doesn't love a wombat?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-373/#TASK2" rel="noopener noreferrer"&gt;Task Description&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;You are given a list and a non-negative integer, &lt;code&gt;$n&lt;/code&gt;. Write a script to divide the given list into &lt;code&gt;$n&lt;/code&gt; equal parts. Return -1 if &lt;code&gt;$n&lt;/code&gt; is more than the size of the list.&lt;/p&gt;

&lt;h5&gt;
  
  
  Example 1
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input: @list = ( 1,2,3,4,5), $n = 2
Output: ((1,2,3), (4,5))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;5 / 2 = 2 remainder 1. The extra element goes into the first chunk.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example 2
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input: @list = (1,2,3,4,5,6), $n = 3
Output: ((1,2), (3,4), (5,6))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;6 / 3 = 2 remainder 0.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example 3
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input: @list = (1,2,3), $n = 2
Output: ((1,2), (3))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Example 4
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input: @list = (1,2,3,4,5,6,7,8,9,10), $n = 5
Output: ((1,2), (3,4), (5,6), (7,8), (9,10))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Example 5
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input: @list = (1,2,3), $n = 4
Output: -1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Example 6
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input: @list = (72,57,89,55,36,84,10,95,99,35), $n = 7;
Output: ((72,57), (89,55), (36,84), (10), (95), (99), (35))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Elaboration
&lt;/h2&gt;

&lt;p&gt;There's some simple modulo division here, and then a decision about what to do if it doesn't divide evenly into &lt;code&gt;$n&lt;/code&gt; chunks. We could put the remainder into a chunk of its own, ignore the remainder, or we could distribute the leftovers in some way that feels balanced -- here, the specification implies that the bigger divisions should go at the front of the list.&lt;/p&gt;

&lt;p&gt;Handling an invalid input (where &lt;code&gt;$n&lt;/code&gt; is too big) by returning -1 instead of an array is a code smell. Having a function that returns different types of things is awkward to handle and error-prone. It would be more consistent to either throw an exception, or return an out-of-range value of the same type, such as an empty array or a null reference. But that wanker Kevin with his six months of Javascript experience got promoted to project manager for some reason &lt;em&gt;&amp;lt;cough/&amp;gt;nepotism&amp;lt;cough&amp;gt;&lt;/em&gt; and that's the requirement we have.&lt;/p&gt;

&lt;p&gt;This task has six examples, and usually we're given five. Is there some significance to this? Example 6 doesn't seem to add any new information beyond what we've already been given. But then we notice that the numbers could be ASCII characters, spelling "H9Y7$T?_c#". I'm pretty sure this is Kevin's password. Watch your back, Kevin.&lt;/p&gt;

&lt;h2&gt;
  
  
  To the CodeMobile, Robin!
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;listDivision&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@$list&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$extra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@answer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$extra&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@answer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@$list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$chunk&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;@$list&lt;/span&gt;   &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@answer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nb"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@$list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$chunk&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;@answer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The input parameters are an array and a number, which forces us to confront the way that Perl passes arguments as a flat list. Here, I've chosen to pass an array reference for &lt;code&gt;$list&lt;/code&gt; instead of an array, which accomplishes two things: it removes the flat list problem to make it obvious which parameter is &lt;code&gt;$n&lt;/code&gt;, and it's more efficient than passing a copy of the array. I could have also passed the parameters in the other order, but "project manager" Kevin said according to ChatGPT &lt;em&gt;and&lt;/em&gt; Claude it had to be in this order, so yeah, that's that then.&lt;/p&gt;

&lt;p&gt;Time to be serious. We dispense with the special case of returning -1 (more on that later). Then we calculate the quantities involved, and set up an array for producing the answer, initially empty.&lt;/p&gt;

&lt;p&gt;The answer has two segments: a head part where there might be one extra element, and the tail part where the segments are of the calculated chunk size. One &lt;code&gt;while&lt;/code&gt; loop ticks off the extra-sized chunks, and the second &lt;code&gt;while&lt;/code&gt; loop completes the division.&lt;/p&gt;

&lt;p&gt;To grab a group of contiguous elements from a list, the &lt;code&gt;splice&lt;/code&gt; function seems like the obvious thing to do. Each &lt;code&gt;splice&lt;/code&gt; is surrounded with &lt;code&gt;[]&lt;/code&gt; so that the chunks are treated as array references. An alternative would have been to take an array slice, but that would introduce index variables for the range being sliced, which looks and feels more complicated and error-prone.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;splice&lt;/code&gt; reduces the size of the list every time it's called, so the second &lt;code&gt;while&lt;/code&gt; loop can use the size of &lt;code&gt;$list&lt;/code&gt; as its condition. However, we are destroying &lt;code&gt;$list&lt;/code&gt; as we go, so the calling function needs to be aware that the array it passed in is no longer valid. If it were important to keep the original list, a copy would need to be made either from the caller, or near the beginning of &lt;code&gt;listDivision()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's think a moment about how to use this function. When it's called it could return either an array of arrays (references actually), or it could return a scalar -1. Here's how I wanted to write the script to use this function, using &lt;code&gt;-n&lt;/code&gt; as a command-line option to get that parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;GetOpt::&lt;/span&gt;&lt;span class="nv"&gt;Long&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;GetOptions&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;n:i&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;$N&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;listDivision&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;@ARGV&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$N&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nv"&gt;showAofA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$div&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;showAofA()&lt;/code&gt; is a function that formats the array of arrays into a parenthesized list of comma-separated lists, as in the examples.&lt;/p&gt;

&lt;p&gt;However, &lt;code&gt;$div&lt;/code&gt; isn't always a reference; sometimes it's a scalar -1. That throws up an ugly error about trying to use a scalar value as a reference. The way to check what's behind a variable in Perl is to use the &lt;a href="https://perldoc.perl.org/functions/ref" rel="noopener noreferrer"&gt;ref&lt;/a&gt; function. It will give a string identifying the variable type, or, for a scalar, it will give an empty string. In perl, an empty string counts as false. So, to satisfy the requirement, the script needs to test whether &lt;code&gt;ref($div)&lt;/code&gt; is empty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$div&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;showAofA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$div&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$div&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I probably should have done is change &lt;code&gt;listDivision&lt;/code&gt; so that it consistently returns an array reference, but for the invalid case, throws an error. Variations on try/catch have been available as modules in Perl for decades, but it &lt;em&gt;finally&lt;/em&gt; (see what I did there?) became official in version 5.38. That simplifies the usage of the function (if you consider try/catch simpler, which some consider a debatable topic).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;try&lt;/span&gt;          &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nv"&gt;showAofA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;listDivision&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nv"&gt;@ARGV&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make the function throw an exception, we only need to change the early return from the function into a &lt;code&gt;die&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;listDivision&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;n&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@$list&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;N out of range (must be &amp;lt;= &lt;/span&gt;&lt;span class="si"&gt;$size&lt;/span&gt;&lt;span class="s2"&gt;)&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# [ ... ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's cleaner, but it slightly complicates the unit testing, because now we have to test for exceptions. The incantation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;runTest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::&lt;/span&gt;&lt;span class="nv"&gt;V0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::Tools::&lt;/span&gt;&lt;span class="nv"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# [Test cases that should work&lt;/span&gt;
    &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;listDivision&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;One chunk&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
    &lt;span class="c1"&gt;# [ ... ]&lt;/span&gt;
    &lt;span class="c1"&gt;# Test things that throw exceptions&lt;/span&gt;
    &lt;span class="nv"&gt;like&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;dies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;listDivision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="sx"&gt;qr/out of range/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;dies&lt;/code&gt; function returns the exception string that results from trying to execute a code block, and &lt;code&gt;like&lt;/code&gt; does a pattern match against the expected exception.&lt;/p&gt;

&lt;p&gt;And finally, to tidy up a loose end, here's the &lt;code&gt;showAofA()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;showAofA&lt;/span&gt;&lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="p"&gt;('&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="p"&gt;',&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;)&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;$ref&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;)&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a bunch of punctuation out of that so that we can see the structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$ref&lt;/code&gt; is a reference to an array of references; hence, &lt;code&gt;$ref-&amp;gt;@*&lt;/code&gt; is de-referencing it to yield a list of array references.&lt;/p&gt;

&lt;p&gt;Each of those array references is then transformed by &lt;code&gt;map&lt;/code&gt;. Inside the &lt;code&gt;map {}&lt;/code&gt; block, &lt;code&gt;$_&lt;/code&gt; refers to one of the inner arrays, so we de-reference that (&lt;code&gt;$_-&amp;gt;@*&lt;/code&gt;) to get a list of numbers, which we will join into a comma-separated string. Wrap that with a pair of parentheses, and out of the &lt;code&gt;map&lt;/code&gt; comes the inner lists formatted as needed.&lt;/p&gt;

&lt;p&gt;Now each of the inner lists is a string. The outer &lt;code&gt;join&lt;/code&gt; inserts commas to make it a list of lists, and finally we wrap the whole thing in parentheses to complete the string.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
    <item>
      <title>PWC 371 Subset Equilibrium (Just nod if you can hear me)</title>
      <dc:creator>Bob Lied</dc:creator>
      <pubDate>Tue, 28 Apr 2026 13:02:35 +0000</pubDate>
      <link>https://dev.to/boblied/pwc-371-subset-equilibrium-just-nod-if-you-can-hear-me-14im</link>
      <guid>https://dev.to/boblied/pwc-371-subset-equilibrium-just-nod-if-you-can-hear-me-14im</guid>
      <description>&lt;p&gt;Another explosive weekly challenge. And by explosive I mean exponential complexity. Let's see what we've got. First I'll adjust the background music for equilibrium ... &lt;a href="https://www.youtube.com/watch?v=7f3EGjRxxNI&amp;amp;list=RD7f3EGjRxxNI&amp;amp;start_radio=1" rel="noopener noreferrer"&gt;Comfortably Numb&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Relax, I'll Need Some Information First
&lt;/h2&gt;

&lt;p&gt;You are given an array of numbers.  Write a script to find all subsets where the sum of elements equals the sum of their indices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Example 1 Input: @nums = (2, 1, 4, 3)
#.          Output: (2, 1), (1, 4), (4, 3), (2, 3)
#   Subset 1: (2, 1) Values: 2 + 1 = 3 Positions: 1 + 2 = 3
#   Subset 2: (1, 4) Values: 1 + 4 = 5 Positions: 2 + 3 = 5
#   Subset 3: (4, 3) Values: 4 + 3 = 7 Positions: 3 + 4 = 7
#   Subset 4: (2, 3) Values: 2 + 3 = 5 Positions: 1 + 4 = 5
#
# Example 2 Input: @nums = (3, 0, 3, 0)
#           Output: (3, 0), (3, 0, 3)
#   Subset 1: (3, 0) Values: 3 + 0 = 3 Positions: 1 + 2 = 3
#   Subset 2: (3, 0, 3) Values: 3 + 0 + 3 = 6 Positions: 1 + 2 + 3 = 6
#
# Example 3 Input: @nums = (5, 1, 1, 1)
#           Output: (5, 1, 1)
#   Subset 1: (5, 1, 1) Values: 5 + 1 + 1 = 7 Positions: 1 + 2 + 4 = 7
#
# Example 4 Input: @nums = (3, -1, 4, 2)
#           Output: (3, 2), (3, -1, 4)
#   Subset 1: (3, 2) Values: 3 + 2 = 5 Positions: 1 + 4 = 5
#   Subset 2: (3, -1, 4) Values: 3 + (-1) + 4 = 6 Positions: 1 + 2 + 3 = 6
#
# Example 5 Input: @nums = (10, 20, 30, 40)
#           Output: ()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Just the Basic Facts, Can You Show Me Where It Hurts?
&lt;/h2&gt;

&lt;p&gt;Perusing the examples, I see that there are a couple of unstated requirements. From example 1, the improper subset (1,2,3,4) should work, but it's not in the given output, so apparently that should be excluded. And in example two, the subset (3) should work, but it's not in the output, so apparently subsets have to have at least two members.&lt;/p&gt;

&lt;p&gt;I don't see any way of doing this other than generating all possible subsets and checking if they work. My approach is going to be to number the positions, and generate all possible subsets of the positions. Extracting members from the given list will be done with a hash slice. There's going to be a little annoyance that the task numbers positions starting from 1, while Perl array indexing is based from 0. &lt;/p&gt;

&lt;p&gt;For a set of &lt;em&gt;n&lt;/em&gt; members, there are 2&lt;sup&gt;&lt;em&gt;n&lt;/em&gt;&lt;/sup&gt;-1 possible subsets. I know that a way to generate subsets is to count from 1 to 2&lt;sup&gt;&lt;em&gt;n&lt;/em&gt;&lt;/sup&gt;-1 and check which bits are 1s in the binary representation. I know how to generate all possible subsets, but do I want to? Because I also know that there are CPAN modules that do this, and I have &lt;a href="https://metacpan.org/pod/Algorithm::Combinatorics#subsets" rel="noopener noreferrer"&gt;&lt;code&gt;Algorithm::Combinatorics&lt;/code&gt;&lt;/a&gt; hanging around from previous problems, with its convenient &lt;code&gt;subsets&lt;/code&gt; function, so let's use that.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Do Believe It's Working, Good
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;sseq&lt;/span&gt;&lt;span class="err"&gt;(@&lt;/span&gt;&lt;span class="nf"&gt;nums&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Algorithm::&lt;/span&gt;&lt;span class="nv"&gt;Combinatorics&lt;/span&gt; &lt;span class="sx"&gt;qw/subsets/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;List::&lt;/span&gt;&lt;span class="nv"&gt;Util&lt;/span&gt; &lt;span class="sx"&gt;qw/sum0/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;subsets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="nv"&gt;$#nums&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;scalar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@$position&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;# Only proper subsets of size 2 or more&lt;/span&gt;
        &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;scalar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;# Subsets are indexed at zero, but positions at 1, so compensate in sum&lt;/span&gt;
        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$sumPosition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;sum0&lt;/span&gt;  &lt;span class="nv"&gt;@$position&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$sumNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;sum0&lt;/span&gt; &lt;span class="nv"&gt;@nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;@$position&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$sumNumbers&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$sumPosition&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;push&lt;/span&gt; &lt;span class="nv"&gt;@result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;@nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;@$position&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;@result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Your Lips Move, But I Can't Hear What You're Saying
&lt;/h3&gt;

&lt;p&gt;Explanatory notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;use Algorithm::Combinatorics qw/subsets/&lt;/code&gt; -- This function creates an iterator to generate consecutive subsets from a given list of members. We're going to pass it a list of positions, from 0 to the last index of &lt;code&gt;@nums&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;use List::Util qw/sum0/&lt;/code&gt; -- &lt;code&gt;sum0&lt;/code&gt; handles empty lists by returning zero instead of an error, as &lt;code&gt;sum&lt;/code&gt; does. That shouldn't come up in this particular function, but I generally use &lt;code&gt;sum0&lt;/code&gt; as my default, because I invariably get a warning from &lt;code&gt;sum&lt;/code&gt; about an empty array and end up changing it anyway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;my $size = scalar(@$position)&lt;/code&gt; -- the size of the &lt;code&gt;position&lt;/code&gt; array comes up repeatedly, so let's get a handle on it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;my @sumPosition = $size + sum0(...)&lt;/code&gt; -- The sum we're looking for is based on using positions numbered from 1, but we have them numbered from 0. We need to add 1 to each of the positions, which is the same as adding the number of positions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;my @sumNumbers = sum0 @nums[ @$position ]&lt;/code&gt; -- Here's why I wanted positions to be indexed from zero: so that they could be used in a hash slice to extract the corresponding numbers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;push @result, [@nums[@$position]]&lt;/code&gt; -- the result of this function is going to be a reference to an array of arrays (it's array reference turtles all the way down). Once again, the hash slice, now encased in &lt;code&gt;[]&lt;/code&gt; to create an array reference.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  That'll Keep You Going Through the Show
&lt;/h2&gt;

&lt;p&gt;This function answers the question, but it leaves two things undone.&lt;/p&gt;

&lt;p&gt;First, the order of the lists is unspecified. There's no apparent reason for the order in the examples, and I quickly found out that the &lt;code&gt;subsets&lt;/code&gt; iterator doesn't return subsets in the same order as the examples.&lt;/p&gt;

&lt;p&gt;To create unit tests, I want to check that arrays contain the same members, but order doesn't matter. In the &lt;code&gt;Test2&lt;/code&gt; suite, this can be accomplished by putting the expected elements into a bag data structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;runTest&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::&lt;/span&gt;&lt;span class="nv"&gt;V0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;Test2::Tools::&lt;/span&gt;&lt;span class="nv"&gt;Compare&lt;/span&gt; &lt;span class="sx"&gt;qw/bag item/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$check&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;bag&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="nv"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nv"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;sseq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$check&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Example 1&lt;/span&gt;&lt;span class="p"&gt;");&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our bags are checked, so ...&lt;/p&gt;

&lt;h2&gt;
  
  
  Come On, It's Time To Go
&lt;/h2&gt;

&lt;p&gt;Second, to display the output, we have to unwrap the array references and render them as formatted strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt;&lt;span class="p"&gt;("&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;)&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;sseq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@ARGV&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;@*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's going on here?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sseq(@ARGV)-&amp;gt;@*&lt;/code&gt; -- Call our function, using the command line arguments, and dereference it (which yields an array of array references).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;map { ... }&lt;/code&gt; -- Transform each of the array references&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"(" . join(", ", $_-&amp;gt;@*) . ")"&lt;/code&gt; -- &lt;code&gt;$_&lt;/code&gt; is a reference to an array, so &lt;code&gt;$_-&amp;gt;@*&lt;/code&gt; is the list of elements in the array. Make it a comma-separated string, encased in parentheses.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;say join ", ", ...&lt;/code&gt; -- output each of those parenthesized strings, separated by commas&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I Have Become Comfortably Numb
&lt;/h2&gt;

&lt;p&gt;Equilibrium achieved.&lt;/p&gt;

</description>
      <category>perl</category>
      <category>perlweeklychallenge</category>
      <category>pwc</category>
    </item>
  </channel>
</rss>
