<?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>Forem: Simon Green</title>
    <description>The latest articles on Forem by Simon Green (@simongreennet).</description>
    <link>https://forem.com/simongreennet</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F472699%2Feb7bd146-a3b0-41a6-a0b4-22653730bb55.png</url>
      <title>Forem: Simon Green</title>
      <link>https://forem.com/simongreennet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/simongreennet"/>
    <language>en</language>
    <item>
      <title>Weekly Challenge: Group Tag</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Wed, 15 Apr 2026 07:51:08 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challenge-group-tag-k56</link>
      <guid>https://forem.com/simongreennet/weekly-challenge-group-tag-k56</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 369
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, Copilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-369/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-369/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Valid Tag
&lt;/h2&gt;

&lt;p&gt;Submitted by: Mohammad Sajid Anwar&lt;/p&gt;

&lt;p&gt;You are given a given a string caption for a video.&lt;/p&gt;

&lt;p&gt;Write a script to generate tag for the given string caption in three steps as mentioned below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Format as camelCase
Starting with a lower-case letter and capitalising the first letter of each subsequent word: Merge all words in the caption into a single string starting with a #.&lt;/li&gt;
&lt;li&gt;Sanitise the String: Strip out all characters that are not English letters (a-z or A-Z).&lt;/li&gt;
&lt;li&gt;Enforce Length: If the resulting string exceeds 100 characters, truncate it so it is exactly 100 characters long.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;The last example - where &lt;code&gt;Hour&lt;/code&gt; starts with a upper case letter - would suggest that the second step needs to be done before the first one. As I used TDD when writing these solutions this was picked up when running the tests.&lt;/p&gt;

&lt;p&gt;Nothing overly tricky about the solution. I take &lt;code&gt;input_string&lt;/code&gt; and perform the necessary operations on it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;valid_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;input_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[^\sa-zA-Z]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;input_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;input_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; +([a-z])&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;upper_case_letter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="mi"&gt;99&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 solution is similar.&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;main&lt;/span&gt; &lt;span class="p"&gt;($input_string) {&lt;/span&gt;
    &lt;span class="nv"&gt;$input_string&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/[^\sa-zA-Z]//g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$input_string&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/^\s+//&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$input_string&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/\s+$//&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$input_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;lc&lt;/span&gt; &lt;span class="nv"&gt;$input_string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$input_string&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/ +([a-z])/uc $1/&lt;/span&gt;&lt;span class="nv"&gt;eg&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;#&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;$input_string&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;99&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"Cooking with 5 ingredients!"&lt;/span&gt;
&lt;span class="c"&gt;#cookingWithIngredients&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py the-last-of-the-mohicans
&lt;span class="c"&gt;#thelastofthemohicans&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"  extra spaces here"&lt;/span&gt;
&lt;span class="c"&gt;#extraSpacesHere&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"iPhone 15 Pro Max Review"&lt;/span&gt;
&lt;span class="c"&gt;#iphoneProMaxReview&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"Ultimate 24-Hour Challenge: Living in a Smart Home controlled entirely by Artificial Intelligence and Voice Commands in the year 2026!"&lt;/span&gt;
&lt;span class="c"&gt;#ultimateHourChallengeLivingInASmartHomeControlledEntirelyByArtificialIntelligenceAndVoiceCommandsIn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Group Division
&lt;/h2&gt;

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

&lt;p&gt;You are given a string, group size and filler character.&lt;/p&gt;

&lt;p&gt;Write a script to divide the string into groups of given size. In the last group if the string doesn’t have enough characters remaining fill with the given filler character.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This is one task where the Python and Perl solutions are completely different. Python's &lt;code&gt;more_itertools&lt;/code&gt; module has the &lt;a href="https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.grouper" rel="noopener noreferrer"&gt;grouper&lt;/a&gt; function, so I use this to separate the string into parts with the filler if required. No need to reinvent a perfectly round wheel :)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;group_division&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;result&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="n"&gt;g&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;grouper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fillvalue&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;filler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perl does not have a similar function, that I'm aware of. I use a traditional &lt;code&gt;for&lt;/code&gt; loop to split the string into the different parts. After that I have a command that will add the filler to the last item in the &lt;code&gt;@result&lt;/code&gt; array if required. The &lt;code&gt;x&lt;/code&gt; operator is the replication operator in Perl.&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;main&lt;/span&gt; &lt;span class="p"&gt;( $input_string, $size, $filler ) {&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="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;for&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="nv"&gt;$i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&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;$input_string&lt;/span&gt;&lt;span class="p"&gt;)&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="nv"&gt;$size&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="nb"&gt;substr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$input_string&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="nv"&gt;$size&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$result&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="o"&gt;.=&lt;/span&gt; &lt;span class="nv"&gt;$filler&lt;/span&gt; &lt;span class="nv"&gt;x&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="nb"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$result&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="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;(&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="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nv"&gt;@result&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py RakuPerl 4 &lt;span class="s2"&gt;"#"&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Raku'&lt;/span&gt;, &lt;span class="s1"&gt;'Perl'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py Python 5 0
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Pytho'&lt;/span&gt;, &lt;span class="s1"&gt;'n0000'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 12345 3 x
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'123'&lt;/span&gt;, &lt;span class="s1"&gt;'45x'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py HelloWorld 3 _
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Hel'&lt;/span&gt;, &lt;span class="s1"&gt;'loW'&lt;/span&gt;, &lt;span class="s1"&gt;'orl'&lt;/span&gt;, &lt;span class="s1"&gt;'d__'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py AI 5 &lt;span class="s2"&gt;"!"&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'AI!!!'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>perl</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Weekly Challenge: Little, Big and Bigger</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Sun, 12 Apr 2026 08:45:22 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challenge-little-big-and-bigger-jpe</link>
      <guid>https://forem.com/simongreennet/weekly-challenge-little-big-and-bigger-jpe</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 368
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, Copilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-368/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-368/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Make it Bigger
&lt;/h2&gt;

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

&lt;p&gt;You are given a given a string number and a character digit.&lt;/p&gt;

&lt;p&gt;Write a script to remove exactly one occurrence of the given character digit from the given string number, resulting the decimal form is maximised.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;As all the examples are positive integers, I've assumed that the string number is always this. Sometimes brute force is the easiest way to write a solution a task.&lt;/p&gt;

&lt;p&gt;I start my turning the &lt;code&gt;number&lt;/code&gt; and &lt;code&gt;digit&lt;/code&gt; values into strings, and check the digit is in the number. I set the &lt;code&gt;max_number&lt;/code&gt; variable to &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_it_bigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The digit &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is not in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;max_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then create a loop with the variable &lt;code&gt;i&lt;/code&gt; from 0 to one less than the length of the number. If the digit at that position is the &lt;code&gt;digit&lt;/code&gt; value, I compute the number with that digit removed, and update &lt;code&gt;max_number&lt;/code&gt; if required.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Don't consider removing this digit
&lt;/span&gt;            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;new_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;new_number&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;max_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_number&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;max_number&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Perl solution follows the same logic, and uses the &lt;code&gt;substr&lt;/code&gt; method to extract parts of the string.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 15456 5
1546

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 7332 3
732

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 2231 2
231

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 543251 5
54321

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 1921 1
921
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Big and Little Omega
&lt;/h2&gt;

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

&lt;p&gt;You are given a positive integer &lt;code&gt;$number&lt;/code&gt; and a mode flag &lt;code&gt;$mode&lt;/code&gt;. If the mode flag is zero, calculate little omega (the count of all distinct prime factors of that number). If it is one, calculate big omega (the count of all prime factors including duplicates).&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;For this task, I start by computing all the prime factors and storing them in the &lt;code&gt;factors&lt;/code&gt; list (array in Perl). To do this, I start with the variable &lt;code&gt;i&lt;/code&gt; as &lt;code&gt;2&lt;/code&gt; (the smallest prime number). I have a loop that continues until the &lt;code&gt;number&lt;/code&gt; variable is &lt;code&gt;1&lt;/code&gt;. For each iteration, I check if &lt;code&gt;number&lt;/code&gt; is evenly divisible by &lt;code&gt;i&lt;/code&gt;. If it is, I add &lt;code&gt;i&lt;/code&gt; to the &lt;code&gt;factors&lt;/code&gt; list, and &lt;code&gt;divide&lt;/code&gt; number by &lt;code&gt;i&lt;/code&gt;. If it isn't, I increment &lt;code&gt;i&lt;/code&gt; by 1.&lt;/p&gt;

&lt;p&gt;To avoid an endless loop, I have a safety check to see that &lt;code&gt;i&lt;/code&gt; isn't greater than &lt;code&gt;number&lt;/code&gt;. That should never happen, but you never know with user input, or dodgy code :)&lt;/p&gt;

&lt;p&gt;The final part of the task is to return a number based on the &lt;code&gt;mode&lt;/code&gt; value. If the mode is non-zero, I return the number of items in the &lt;code&gt;factors&lt;/code&gt; list. If it is zero, I convert this to set first to count the number of unique factors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;omega&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;factors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;number&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&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="n"&gt;factors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;//=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot calculate prime digits&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factors&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 100061 0
3

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 971088 0
3

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 63640 1
6

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 988841 1
2

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 211529 0
2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Weekly Challenge: Maximum conflict</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Sun, 05 Apr 2026 10:02:03 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challenge-maximum-conflict-5c4n</link>
      <guid>https://forem.com/simongreennet/weekly-challenge-maximum-conflict-5c4n</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 367
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, Copilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-367/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-367/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Max Odd Binary
&lt;/h2&gt;

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

&lt;p&gt;You are given a binary string that has at least one &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Write a script to rearrange the bits in such a way that the resulting binary number is the maximum odd binary number and return the resulting binary string. The resulting string can have leading zeros.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This task requires some number theory to implement the solution.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To make an odd binary number the last bit (less significant) needs to be a 1.&lt;/li&gt;
&lt;li&gt;To make the largest possible number, the remaining set bits need to be the largest (left / most significant) bits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The parts of this task are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use a regular expression to check the &lt;code&gt;input_string&lt;/code&gt; variable matches the expected input. It must contain at least one &lt;code&gt;1&lt;/code&gt; and any number of &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Count the number of zeros and ones in the string, stored as the variables &lt;code&gt;zeros&lt;/code&gt; and &lt;code&gt;ones&lt;/code&gt; respectively.&lt;/li&gt;
&lt;li&gt;Return a string that was &lt;code&gt;ones-1&lt;/code&gt; ones, &lt;code&gt;zeros&lt;/code&gt; zeros and the last one to make it an odd binary.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;max_odd_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&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="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^[01]*1[01]*$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Input not in expected format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;zeros&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ones&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ones&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Perl solution follows the same logic. It uses the &lt;a href="https://perldoc.perl.org/perlop#Transliteration-Quote-Like-Operators" rel="noopener noreferrer"&gt;tr&lt;/a&gt; function to count the number of zeros and ones, and the &lt;a href="https://perldoc.perl.org/perlop#Multiplicative-Operators" rel="noopener noreferrer"&gt;x operator&lt;/a&gt; for repetition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 1011
1101

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 100
001

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 111000
110001

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 0101
1001

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 1111
1111
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Conflict Events
&lt;/h2&gt;

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

&lt;p&gt;You are given two events start and end time.&lt;/p&gt;

&lt;p&gt;Write a script to find out if there is a conflict between the two events. A conflict happens when two events have some non-empty intersection.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;One of the challenges when completing these tasks is achieving the most optimal solutions. Not in terms of performance, but in terms of being the best solution. Usually it is straight forward, I'm not sure if I've hit the mark on this one.&lt;/p&gt;

&lt;p&gt;Things get more complicated when one (or both) the times go across midnight. This is the approach I took.&lt;/p&gt;

&lt;p&gt;Create a function &lt;code&gt;hm2m&lt;/code&gt; to convert a time in HH:MM format to minutes after midnight. It also uses a regular expression to check that the HH:MM is in the correct format and is valid.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hm2m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^([0-1][0-9]|2[0-3]):[0-5][0-9]$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Input is not in the expected format (HH:MM)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&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="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take the supplied events (although the tasks specifies two, more can be provided) and create a &lt;a href="https://docs.python.org/3.12/library/stdtypes.html#range" rel="noopener noreferrer"&gt;range&lt;/a&gt; object from the start time to one minute less than the stop time and store it in the &lt;code&gt;event_minutes&lt;/code&gt; list. If the &lt;code&gt;start_time&lt;/code&gt; is later than &lt;code&gt;end_time&lt;/code&gt; I add two range objects, one before midnight (end time = 1440) and after midnight (start time = 0).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;conflict_events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Determine if there is a conflict between two or more events.

    Params:
        events(list): A list of start and end times in HH:MM format

    Returns:
        bool: Whether two events conflict (occur at the same time)
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;event_minutes&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="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;start_minute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hm2m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&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="n"&gt;end_minute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hm2m&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&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;if&lt;/span&gt; &lt;span class="n"&gt;start_minute&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;end_minute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;end_minute&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;start_minute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;event_minutes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start_minute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1440&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;range&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="n"&gt;end_minute&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="n"&gt;event_minutes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start_minute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end_minute&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final step is to take the &lt;code&gt;event_minutes&lt;/code&gt; ranges, and see if there is any overlap. For this I have a &lt;code&gt;minutes&lt;/code&gt; set (hash in Perl). I iterate over each minute in each item in the &lt;code&gt;events_minutes&lt;/code&gt; list. If the minute already appears in the &lt;code&gt;minutes&lt;/code&gt; set, I return &lt;code&gt;True&lt;/code&gt;. If not, I added it to the &lt;code&gt;minutes&lt;/code&gt; set, and continue the loop.&lt;/p&gt;

&lt;p&gt;If the list is exhausted, I return &lt;code&gt;False&lt;/code&gt; as there is no conflict. Lucky you!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;event_minutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;minute&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;minute&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
            &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Perl solution follows the same logic. The &lt;code&gt;event_minutes&lt;/code&gt; array stores an array of start minutes and end minutes, as it does not have a range-like object.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 10:00 12:00 11:00 13:00
True

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 09:30 10:30 10:30 12:00
False

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 14:00 15:30 14:30 16:00
True

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 08:00 09:00 09:01 10:00
False

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 23:00 00:30 00:00 01:00
True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Happy 7th birthday TWC!</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Mon, 23 Mar 2026 12:34:59 +0000</pubDate>
      <link>https://forem.com/simongreennet/happy-7th-birthday-twc-lpk</link>
      <guid>https://forem.com/simongreennet/happy-7th-birthday-twc-lpk</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 366
&lt;/h2&gt;

&lt;p&gt;It was seven years ago that Mohammad sent out the &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-001/" rel="noopener noreferrer"&gt;first challenge&lt;/a&gt; to Team PWC (as it was then known). Thank you very much for all your work over the seven years.&lt;/p&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, Copilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-366/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-366/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Count Prefixes
&lt;/h2&gt;

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

&lt;p&gt;You are given an array of words and a string (contains only lowercase English letters).&lt;/p&gt;

&lt;p&gt;Write a script to return the number of words in the given array that are a prefix of the given string.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This is a one-liner in Python. It should be pretty self-explanatory. Given a list called &lt;code&gt;array&lt;/code&gt; and a string called &lt;code&gt;prefix&lt;/code&gt;, it counts the number of items in the list where the first letters of the prefix match the word.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_prefixes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&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;The Perl solution uses the grep function to perform the counting. In a scalar context, grep returns the number of matching items.&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;main&lt;/span&gt; &lt;span class="p"&gt;(@array) {&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;@array&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="nb"&gt;grep&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;$prefix&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="nb"&gt;length&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="ow"&gt;eq&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@array&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;$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;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py a ap app apple banana apple
4

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="nb"&gt;cat &lt;/span&gt;dog fish bird
0

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py hello he hello heaven he hello
4

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;""&lt;/span&gt; code coding cod coding
3

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py p &lt;span class="nb"&gt;pr &lt;/span&gt;pro prog progr progra program program
7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Valid Times
&lt;/h2&gt;

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

&lt;p&gt;You are given a time in the form &lt;code&gt;HH:MM&lt;/code&gt;. The earliest possible time is &lt;code&gt;00:00&lt;/code&gt; and the latest possible time is &lt;code&gt;23:59&lt;/code&gt;. In the string time, the digits represented by the &lt;code&gt;?&lt;/code&gt; symbol are unknown, and must be replaced with a digit from 0 to 9.&lt;/p&gt;

&lt;p&gt;Write a script to return the count different ways we can make it a valid time.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This is an interesting challenge as the solution is not straight forward. There are a few approaches that can be taken. One option is to calculate all 1440 minutes in a day and see if it matched the expected pattern.&lt;/p&gt;

&lt;p&gt;The approach I took was to calculate the possible hours and possible minutes, and multiplying both figures to return a result.&lt;/p&gt;

&lt;p&gt;I start by using a regular expression to check if the time is valid. As the question mark &lt;code&gt;?&lt;/code&gt; is within square brackets &lt;code&gt;[ ]&lt;/code&gt; this is taken as a literal character.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;valid_times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^([0-1?][0-9?]|2[0-3?]):[0-5?][0-9?]$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Input is not in the expected format (HH:MM)&lt;/span&gt;&lt;span class="sh"&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 next task is calculating the number of valid hours.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If the hours is &lt;code&gt;??&lt;/code&gt;, then there are 24 valid hours.&lt;/li&gt;
&lt;li&gt;If the first character is a question there are 3 valid hours if the second digit is less than four (e.g. 02 12 22), or 2 if it is 4 or greater (e.g. 04 14).&lt;/li&gt;
&lt;li&gt;If the second character is a question mark, there are 4 valid hours if the first digit is 2, or 10 valid hours otherwise.&lt;/li&gt;
&lt;li&gt;If hours have no questions marks, there is only one valid hour.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="c1"&gt;# Compute the hours
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;input_string&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="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;??&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;input_string&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&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="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;input_string&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="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;input_string&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thankfully calculating the number of valid minutes is a little easier.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If the minutes is &lt;code&gt;??&lt;/code&gt;, then there are sixty valid minutes.&lt;/li&gt;
&lt;li&gt;If the first character is a question mark, then there are six valid minutes (e.g. 06 16 26 36 46 56).&lt;/li&gt;
&lt;li&gt;If the second characters is a question mark, there are ten valid minutes (e.g. 50 51 ... 58 59).&lt;/li&gt;
&lt;li&gt;If the minutes have no question marks, there is only one valid minute.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;input_string&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="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;??&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;input_string&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="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;input_string&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="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;minutes&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;return&lt;/span&gt; &lt;span class="n"&gt;hours&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Perl solution follows the same logic as the Python solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py ?2:34
3

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py ?4:?0
12

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py ??:??
1440

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py ?3:45
3

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 2?:15
4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>perl</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Weekly Challenge: Counting the index</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Thu, 19 Mar 2026 07:30:11 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challenge-counting-the-index-oe1</link>
      <guid>https://forem.com/simongreennet/weekly-challenge-counting-the-index-oe1</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 365
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, Copilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-365/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-365/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Alphabet Index Digit Sum
&lt;/h2&gt;

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

&lt;p&gt;You are given a string &lt;code&gt;$str&lt;/code&gt; consisting of lowercase English letters, and an integer &lt;code&gt;$k&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Write a script to convert a lowercase string into numbers using alphabet positions (a=1 … z=26), concatenate them to form an integer, then compute the sum of its digits repeatedly &lt;code&gt;$k&lt;/code&gt; times, returning the final value.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This is a task of two parts. The first is to take the letters from &lt;code&gt;input_string&lt;/code&gt; (as &lt;code&gt;str&lt;/code&gt; is a reserved word in Python) to create a number. For this I use &lt;code&gt;string.ascii_lowercase.index(letter)+1&lt;/code&gt; to get each letter and append it to the &lt;code&gt;digits&lt;/code&gt; variable. The &lt;code&gt;+1&lt;/code&gt; is because the letters start at &lt;code&gt;1&lt;/code&gt;, not &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;aid_sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;digits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;digits&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ascii_lowercase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letter&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;except&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The character &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; does not appear to be a lower case letter&lt;/span&gt;&lt;span class="sh"&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 second part is to compute the sums of all the digits a specified number of times. For this I have a loop that performs this. It's a little clunky as Python treats strings and integers differently. If I have a single digit, I exit the loop early as further repetitions won't change the result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;digits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digits&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;break&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As Perl doesn't care about strings vs integers (with a few exceptions), the code is more straight forward. The &lt;a href="https://perldoc.perl.org/functions/index" rel="noopener noreferrer"&gt;index&lt;/a&gt; function is used to find the position of the letter in the alphabet.&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;main&lt;/span&gt; &lt;span class="p"&gt;( $input_string, $k ) {&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$alphabet&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="p"&gt;"",&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&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="s2"&gt;z&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;$digits&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'';&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$letter&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;$input_string&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;$idx&lt;/span&gt; &lt;span class="o"&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;$alphabet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$letter&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;$idx&lt;/span&gt; &lt;span class="o"&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="nb"&gt;die&lt;/span&gt;
              &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The character '&lt;/span&gt;&lt;span class="si"&gt;$letter&lt;/span&gt;&lt;span class="s2"&gt;' does not appear to be a lower case letter&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$digits&lt;/span&gt; &lt;span class="o"&gt;.=&lt;/span&gt; &lt;span class="nv"&gt;$idx&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;foreach&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="nv"&gt;$digits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;sum&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;$digits&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="nv"&gt;$digits&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;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py abc 1
6

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py az 2
9

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="nb"&gt;cat &lt;/span&gt;1
6

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py dog 2
8

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py perl 3
6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Valid Token Counter
&lt;/h2&gt;

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

&lt;p&gt;You are given a sentence.&lt;/p&gt;

&lt;p&gt;Write a script to split the given sentence into space-separated tokens and count how many are valid words. A token is valid if it contains no digits, has at most one hyphen surrounded by lowercase letters, and at most one punctuation mark (&lt;code&gt;!&lt;/code&gt;, &lt;code&gt;.&lt;/code&gt;, &lt;code&gt;,&lt;/code&gt;) appearing only at the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This is a challenge where regular expression can be used to solve the problem. In both the Python and Perl solution, the regular expression used is &lt;code&gt;^[a-z]+(\-[a-z]+)?[!,\.]?$&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Breaking each part down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;^&lt;/code&gt; indicate the start of the string&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[a-z]+&lt;/code&gt; means one or more lower case letters&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(\-[a-z]+)?&lt;/code&gt; means optionally (the question mark) a hyphen and one or more lowercase letters.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[!,\.]?&lt;/code&gt; means optionally a exclamation mark, comma or full stop.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$&lt;/code&gt; means the end of the string.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a one liner in Python&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;valid_token_counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^[a-z]+(\-[a-z]+)?[!,\.]?$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&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 solution is also one line (and an extra one to display the answer). The &lt;code&gt;grep&lt;/code&gt; function returns the number of matches in a scalar context.&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;main&lt;/span&gt; &lt;span class="p"&gt;($input_string) {&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="nb"&gt;grep&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="sr"&gt;/^[a-z]+(\-[a-z]+)?[!,\.]?$/&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;/\s+/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nv"&gt;$input_string&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;$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;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"cat and dog"&lt;/span&gt;
3

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"a-b c! d,e"&lt;/span&gt;
2

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"hello-world! this is fun"&lt;/span&gt;
4

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"ab- cd-ef gh- ij!"&lt;/span&gt;
2

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"wow! a-b-c nice."&lt;/span&gt;
2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>perl</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Weekly Challenge: It's all about the translation</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Thu, 12 Mar 2026 07:29:35 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challenge-its-all-about-the-translation-17li</link>
      <guid>https://forem.com/simongreennet/weekly-challenge-its-all-about-the-translation-17li</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 364
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, Copilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-364/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-364/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Decrypt String
&lt;/h2&gt;

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

&lt;p&gt;You are given a string formed by digits and &lt;code&gt;#&lt;/code&gt;. Write a script to map the given string to English lowercase characters following the given rules.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Characters &lt;code&gt;a&lt;/code&gt; to &lt;code&gt;i&lt;/code&gt; are represented by &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;9&lt;/code&gt; respectively.&lt;/li&gt;
&lt;li&gt;Characters &lt;code&gt;j&lt;/code&gt; to &lt;code&gt;z&lt;/code&gt; are represented by &lt;code&gt;10#&lt;/code&gt; to &lt;code&gt;26#&lt;/code&gt; respectively.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This task calls for regular expressions to be used. Both Python and Perl allow call back functions in the replacement section (i.e. you can call a function to find the new string).&lt;/p&gt;

&lt;p&gt;For the Python solution, I have a (callback) function called &lt;code&gt;replace_digits&lt;/code&gt;. It takes a Match object as input and returns a string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;replace_digits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&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;return&lt;/span&gt; &lt;span class="nf"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;96&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The variable &lt;code&gt;c&lt;/code&gt; has the matching string (either a single digit or two digits (10-26) followed by a hash character. Things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;c[:2]&lt;/code&gt; will remove the hash if it is present.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;int(...)&lt;/code&gt; will convert this into a number&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chr(...)&lt;/code&gt; will turn this into a letter of the alphabet. The ASCII code for the letter &lt;code&gt;a&lt;/code&gt; is &lt;code&gt;97&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main function checks that the input is valid. It then uses &lt;code&gt;re.sub&lt;/code&gt; to perform the substitution in the &lt;code&gt;replace_digits&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;decrypt_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&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="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^(1\d#|2[0-6]#|\d)*$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;String not in expected format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(1\d#|2[0-6]#|\d)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replace_digits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_string&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 solution follows the same logic, except that the replacement value can be code (not just a function call). This negates the need for a separate function. The &lt;code&gt;substr&lt;/code&gt; function is used to remove the hash character.&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;main&lt;/span&gt; &lt;span class="p"&gt;($input_string) {&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;$input_string&lt;/span&gt; &lt;span class="o"&gt;!~&lt;/span&gt; &lt;span class="sr"&gt;/^(1\d#|2[0-6]#|\d)*$/&lt;/span&gt; &lt;span class="p"&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;String not in expected format&lt;/span&gt;&lt;span class="se"&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;$output_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$input_string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$output_string&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/(1\d#|2[0-6]#|\d)/chr(96 + substr($1,0,2))/&lt;/span&gt;&lt;span class="nv"&gt;eg&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;$output_string&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;In the regular expression, &lt;code&gt;/e&lt;/code&gt; indicates that the replacement value is a expression (as opposed to the literal string), and &lt;code&gt;/g&lt;/code&gt; means to run the regular expression globally (on all occurrences).&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 10#11#12
jkab

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 1326#
acz

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 25#24#123
yxabc

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 20#5
te

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 1910#26#
aijz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Goal Parser
&lt;/h2&gt;

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

&lt;p&gt;You are given a string, &lt;code&gt;$str&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Write a script to interpret the given string using Goal Parser. The Goal Parser interprets &lt;code&gt;G&lt;/code&gt; as the string &lt;code&gt;G&lt;/code&gt;, &lt;code&gt;()&lt;/code&gt; as the string &lt;code&gt;o&lt;/code&gt;, and &lt;code&gt;(al)&lt;/code&gt; as the string &lt;code&gt;al&lt;/code&gt;. The interpreted strings are then concatenated in the original order.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;For this task, I use a regular expression to check that the &lt;code&gt;input_string&lt;/code&gt; is in the expected format. I then use the replace function to change the string to the required output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;good_parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&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="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^(G|\(\)|\(al\))*$&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unexpected input received&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;()&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;o&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;(al)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;al&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perl doesn't have a replace function, so I use a regular expression to perform the replacement.&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;main&lt;/span&gt; &lt;span class="p"&gt;($input_string) {&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;$input_string&lt;/span&gt; &lt;span class="o"&gt;!~&lt;/span&gt; &lt;span class="sr"&gt;/^(G|\(\)|\(al\))*$/&lt;/span&gt;&lt;span class="p"&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;Unexpected input received&lt;/span&gt;&lt;span class="se"&gt;\n&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;my&lt;/span&gt; &lt;span class="nv"&gt;$output_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$input_string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$output_string&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt;&lt;span class="sr"&gt;s/\(\)/o/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$output_string&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;s/\(al\)/al/g&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;$output_string&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;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;Parentheses have special meaning in bash, so quotes are used to handle this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.pl &lt;span class="s2"&gt;"G()(al)"&lt;/span&gt;
Goal

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.pl &lt;span class="s2"&gt;"G()()()()(al)"&lt;/span&gt;
Gooooal

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.pl &lt;span class="s2"&gt;"(al)G(al)()()"&lt;/span&gt;
alGaloo

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.pl &lt;span class="s2"&gt;"()G()G"&lt;/span&gt;
oGoG

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.pl &lt;span class="s2"&gt;"(al)(al)G()()"&lt;/span&gt;
alalGoo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>perl</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Weekly Challlenge: The subnet detector</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Sun, 08 Mar 2026 13:43:08 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challlenge-the-subnet-detector-1d9l</link>
      <guid>https://forem.com/simongreennet/weekly-challlenge-the-subnet-detector-1d9l</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 363
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, CoPilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-363/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-363/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: String Lie Detector
&lt;/h2&gt;

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

&lt;p&gt;You are given a string.&lt;/p&gt;

&lt;p&gt;Write a script that parses a self-referential string and determines whether its claims about itself are true. The string will make statements about its own composition, specifically the number of vowels and consonants it contains.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This was relatively straight forward in Python. I took the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use a regular expression to extract the necessary parts of the &lt;code&gt;input_string&lt;/code&gt;, and store this as the value &lt;code&gt;match&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Count the number of vowels and consonants in the first value and store it as &lt;code&gt;vowel_count&lt;/code&gt; and &lt;code&gt;const_count&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use the &lt;a href="https://pypi.org/project/word2num/" rel="noopener noreferrer"&gt;word2num&lt;/a&gt; module to convert the numbers in &lt;code&gt;input_string&lt;/code&gt; to integers, stored as &lt;code&gt;expected_vowel&lt;/code&gt; and &lt;code&gt;expected_const&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Compare the count and expected values match, and return the result.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;word2num&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;word2num&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;string_lie_detector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(\w+) . (\w+) vowels? and (\w+) consonants?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Input string not in expected format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;vowel_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;const_count&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;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&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="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aeiou&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;vowel_count&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;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;const_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="n"&gt;expected_vowel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;word2num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&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="n"&gt;expected_const&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;word2num&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vowel_count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;expected_vowel&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;const_count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;expected_const&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Perl solution is a little more complex. Maybe my Google-foo isn't up to scratch (and I don't use Copilot when working on solutions) that there doesn't appear to be a CPAN module that will convert words into numbers. As this is a coding exercise only I have a hash called &lt;code&gt;%word2num&lt;/code&gt; that maps words to number (from zero to twenty).&lt;/p&gt;

&lt;p&gt;The next problem is four of the examples use a long dash as the separator. This is a UTF-8 character. The result of &lt;code&gt;perl -E 'say length("—")'&lt;/code&gt; is 3. After numerous searches of the Internet, it turns out I need to include &lt;code&gt;use utf8:all&lt;/code&gt; in the code. With this change, I get the expected result of &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The rest of the code follows the same logic as the Python solution.&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;utf8::&lt;/span&gt;&lt;span class="nv"&gt;all&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;main&lt;/span&gt; &lt;span class="p"&gt;($input_string) {&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%word2num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sx"&gt;qw/
        zero 0 one 1 two 2 three 3 four 4 five 5 six 6 seven 7 eight 8
        nine 9 ten 10 eleven 11 twelve 12 thirteen 13 fourteen 14
        fifteen 15 sixteen 16 seventeen 17 eighteen 18 nineteen 19 twenty 20
    /&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;$word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$c&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;$input_string&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="sr"&gt;/(\w+) . (\w+) vowels? and (\w+) consonants?/&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="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="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;Input string not in expected format&lt;/span&gt;&lt;span class="se"&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;$vowel_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;my&lt;/span&gt; &lt;span class="nv"&gt;$const_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;foreach&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="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="nb"&gt;lc&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;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="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aeiou&lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nv"&gt;$c&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="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;$const_count&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="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$vowel_count&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="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$expected_vowel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$word2num&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;lc&lt;/span&gt; &lt;span class="nv"&gt;$v&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&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;Don't know what &lt;/span&gt;&lt;span class="si"&gt;$v&lt;/span&gt;&lt;span class="s2"&gt; is&lt;/span&gt;&lt;span class="se"&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;$expected_const&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$word2num&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;lc&lt;/span&gt; &lt;span class="nv"&gt;$c&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&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;Don't know what &lt;/span&gt;&lt;span class="si"&gt;$c&lt;/span&gt;&lt;span class="s2"&gt; is&lt;/span&gt;&lt;span class="se"&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;$truth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$vowel_count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$expected_vowel&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nv"&gt;$const_count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$expected_const&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;$truth&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&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;false&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;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;There was an issue with the examples, and I raised a &lt;a href="https://github.com/manwar/theweeklychallenge/pull/207" rel="noopener noreferrer"&gt;pull request&lt;/a&gt; to fix it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"aa — two vowels and zero consonants"&lt;/span&gt;
True

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"iv — one vowel and one consonant"&lt;/span&gt;
True

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"hello - three vowels and two consonants"&lt;/span&gt;
False

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"aeiou — five vowels and zero consonants"&lt;/span&gt;
True

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"aei — three vowels and zero consonants"&lt;/span&gt;
True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Subnet Sheriff
&lt;/h2&gt;

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

&lt;p&gt;You are given an IPv4 address and an IPv4 network (in CIDR format).&lt;/p&gt;

&lt;p&gt;Write a script to determine whether both are valid and the address falls within the network. For more information see the &lt;a href="https://en.wikipedia.org/wiki/IPv4" rel="noopener noreferrer"&gt;Wikipedia article&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This one was the easier of the two to complete. Maybe because I have worked at many IPSs in the past :-)&lt;/p&gt;

&lt;p&gt;Python has the &lt;a href="https://docs.python.org/3/library/ipaddress.html" rel="noopener noreferrer"&gt;ipaddress&lt;/a&gt; module which makes it easy to confirm if an IPv4 address is in a particular IP address block.&lt;/p&gt;

&lt;p&gt;I use a try/except block to handle situations (like the second example) where the IP address or net block is invalid. This follows the Python philosophy of &lt;a href="https://www.geeksforgeeks.org/python/eafp-principle-in-python/" rel="noopener noreferrer"&gt;Easier to Ask for Forgiveness than Permission&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ipaddress&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;subnet_sheriff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip_addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ipaddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;IPv4Address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip_addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ipaddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;IPv4Network&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;ipaddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddressValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perl has the &lt;a href="https://docs.python.org/3/library/ipaddress.html" rel="noopener noreferrer"&gt;Net::IP&lt;/a&gt; module in CPAN that performs similar functionality. If the IP address or net block is invalid, the variable will be &lt;code&gt;undef&lt;/code&gt;, and the else block will be used.&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;Net::&lt;/span&gt;&lt;span class="nv"&gt;IP&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;main&lt;/span&gt; &lt;span class="p"&gt;( $ip_addr, $domain ) {&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$addr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Net::&lt;/span&gt;&lt;span class="nv"&gt;IP&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;$ip_addr&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;$block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Net::&lt;/span&gt;&lt;span class="nv"&gt;IP&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;$domain&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;$addr&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nv"&gt;$block&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;$overlaps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$addr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;overlaps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nv"&gt;$IP_NO_OVERLAP&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;$overlaps&lt;/span&gt;  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&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;false&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="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;false&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;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 192.168.1.45 192.168.1.0/24
True

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 10.0.0.256 10.0.0.0/24
False

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 172.16.8.9 172.16.8.9/32
True

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 172.16.4.5 172.16.0.0/14
True

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 192.0.2.0 192.0.2.0/25
True

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 1.1.1.1 10.0.0.0/8
False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>perl</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Weekly Challenge: The one liners</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Sun, 01 Mar 2026 12:57:45 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challenge-the-one-liners-14lo</link>
      <guid>https://forem.com/simongreennet/weekly-challenge-the-one-liners-14lo</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 362
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, CoPilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-362/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-362/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Echo Chamber
&lt;/h2&gt;

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

&lt;p&gt;You are given a string containing lowercase letters.&lt;/p&gt;

&lt;p&gt;Write a script to transform the string based on the index position of each character (starting from &lt;code&gt;0&lt;/code&gt;). For each character at position &lt;code&gt;i&lt;/code&gt;, repeat it &lt;code&gt;i + 1&lt;/code&gt; times.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;Both of this weeks solutions are a one-liner in Python. For this task, the function is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;echo_chamber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&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;Multiplying a string (&lt;code&gt;letter&lt;/code&gt;) by an integer (&lt;code&gt;pos&lt;/code&gt;) will repeat the string the specified number of times.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.python.org/3/library/functions.html#enumerate" rel="noopener noreferrer"&gt;enumerate&lt;/a&gt; function in Python returns the index and the value from a iterator (in this case characters in a string). A little-used feature of this function is the &lt;code&gt;start&lt;/code&gt; parameter which will start counting at a value other than the default of zero.&lt;/p&gt;

&lt;p&gt;The Perl solution is a little more verbose, as I build the string a letter at a time. By using &lt;code&gt;++$cnt&lt;/code&gt;, the value is incremented before it is evaluated (as opposed to &lt;code&gt;$cnt++&lt;/code&gt;). The &lt;code&gt;x&lt;/code&gt; operator will repeat the string the required number of times.&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;main&lt;/span&gt; &lt;span class="p"&gt;($input_string) {&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$output_string&lt;/span&gt; &lt;span class="o"&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;$cnt&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;foreach&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$letter&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;$input_string&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$output_string&lt;/span&gt; &lt;span class="o"&gt;.=&lt;/span&gt; &lt;span class="nv"&gt;$letter&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nv"&gt;$cnt&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="nv"&gt;$output_string&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;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py abca
abbcccaaaa

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py xyz
xyyzzz

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py code
coodddeeee

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py hello
heelllllllooooo

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py a
a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Spellbound Sorting
&lt;/h2&gt;

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

&lt;p&gt;You are given an array of integers.&lt;/p&gt;

&lt;p&gt;Write a script to return them in alphabetical order, in any language of your choosing. Default language is English.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;Thankfully the perfectly round wheels have already been invented for converting integers into strings. To make this task a little easier on myself, I'm only using English.&lt;/p&gt;

&lt;p&gt;Python has the &lt;a href="https://pypi.org/project/num2words/" rel="noopener noreferrer"&gt;num2words&lt;/a&gt; module. The &lt;a href="https://docs.python.org/3/library/functions.html#sorted" rel="noopener noreferrer"&gt;sorted&lt;/a&gt; function has the key parameter to determine how the integers should be sorted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;num2words&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;num2words&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;spellbound_sorting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;num2words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perl has the &lt;a href="https://metacpan.org/pod/Lingua::EN::Numbers" rel="noopener noreferrer"&gt;Lingua::EN::Numbers&lt;/a&gt; module. The &lt;a href="https://perldoc.perl.org/functions/sort" rel="noopener noreferrer"&gt;sort&lt;/a&gt; function in Perl also has built in features to determine the sort order.&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;Lingua::EN::&lt;/span&gt;&lt;span class="nv"&gt;Numbers&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;num2en&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;main&lt;/span&gt; &lt;span class="p"&gt;(@ints) {&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@sorted_ints&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;num2en&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="ow"&gt;cmp&lt;/span&gt; &lt;span class="nv"&gt;num2en&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;@ints&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;",&lt;/span&gt; &lt;span class="nv"&gt;@sorted_ints&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;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 6 7 8 9 10
&lt;span class="o"&gt;[&lt;/span&gt;8, 9, 7, 6, 10]

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="nt"&gt;-3&lt;/span&gt; 0 1000 99
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-3&lt;/span&gt;, 99, 1000, 0]

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 1 2 3 4 5
&lt;span class="o"&gt;[&lt;/span&gt;5, 4, 1, 3, 2]

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 0 &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;-2&lt;/span&gt; &lt;span class="nt"&gt;-3&lt;/span&gt; &lt;span class="nt"&gt;-4&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-4&lt;/span&gt;, &lt;span class="nt"&gt;-1&lt;/span&gt;, &lt;span class="nt"&gt;-3&lt;/span&gt;, &lt;span class="nt"&gt;-2&lt;/span&gt;, 0]

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py 100 101 102
&lt;span class="o"&gt;[&lt;/span&gt;100, 101, 102]

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

&lt;/div&gt;



</description>
      <category>perl</category>
      <category>python</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Weekly Challenge: Representing a celebrity</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Mon, 16 Feb 2026 06:58:38 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challenge-representing-a-celebrity-1cfe</link>
      <guid>https://forem.com/simongreennet/weekly-challenge-representing-a-celebrity-1cfe</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 361
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, GitHub Copilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-361/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-361/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Zeckendorf Representation
&lt;/h2&gt;

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

&lt;p&gt;You are given a positive integer (&amp;lt;= 100).&lt;/p&gt;

&lt;p&gt;Write a script to return Zeckendorf Representation of the given integer. Every positive integer can be uniquely represented as sum of non-consecutive Fibonacci numbers.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;My original solution was to use a recursive function to calculate the  numbers. This attempt is recorded in &lt;a href="https://github.com/manwar/perlweeklychallenge-club/blob/master/challenge-361/sgreen/python/ch-1-recursive.py" rel="noopener noreferrer"&gt;ch-1-recursive.py&lt;/a&gt;. However, I realized when looking at larger numbers, this was not required. There is a reason this is the first task and not the second :)&lt;/p&gt;

&lt;p&gt;My solution starts with a function called &lt;code&gt;generate_fibonacci&lt;/code&gt; which generates a list of Fibonacci numbers that are less than or equal to the target number. This is stored in a list called &lt;code&gt;seq&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;seq&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;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;seq&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="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seq&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;+&lt;/span&gt; &lt;span class="n"&gt;seq&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;return&lt;/span&gt; &lt;span class="n"&gt;seq&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I create an a variable called &lt;code&gt;remaining&lt;/code&gt; which is set to the input number, and an empty list called &lt;code&gt;result&lt;/code&gt; which has the numbers that make up the solution.&lt;/p&gt;

&lt;p&gt;Next I have a loop that runs until a solution is found, or it the &lt;code&gt;seq&lt;/code&gt; list is empty (which should never happen). For each iteration, I take the last value from the list and assign it to a variable called &lt;code&gt;value&lt;/code&gt;. If this is larger than &lt;code&gt;remaining&lt;/code&gt;, the loop starts again with no further action.&lt;/p&gt;

&lt;p&gt;I subtract &lt;code&gt;value&lt;/code&gt; from &lt;code&gt;remaining&lt;/code&gt;, and append &lt;code&gt;value&lt;/code&gt; to the &lt;code&gt;result&lt;/code&gt; list. If &lt;code&gt;remaining&lt;/code&gt; is zero, the solution is found, and is returned. If the is still a remainder, I remove another value from the &lt;code&gt;seq&lt;/code&gt; list (as we cannot use consecutive numbers), and the loop starts again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;zeckendorf_representation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&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="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The number must be a positive integer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;seq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;
    &lt;span class="n"&gt;result&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="n"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;remaining&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;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

            &lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 4
&lt;span class="o"&gt;[&lt;/span&gt;3, 1]

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 12
&lt;span class="o"&gt;[&lt;/span&gt;8, 3, 1]

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 20
&lt;span class="o"&gt;[&lt;/span&gt;13, 5, 2]

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 96
&lt;span class="o"&gt;[&lt;/span&gt;89, 5, 2]

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 100
&lt;span class="o"&gt;[&lt;/span&gt;89, 8, 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bonus
&lt;/h3&gt;

&lt;p&gt;I'm not sure why there is a restriction on numbers less than 100. Even calculating the Zeckendorf Representation of a &lt;a href="https://en.wikipedia.org/wiki/Googol" rel="noopener noreferrer"&gt;Googol&lt;/a&gt; (10&lt;sup&gt;100&lt;/sup&gt;) takes less than 0.2 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt; ./ch-1.py 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
&lt;span class="o"&gt;[&lt;/span&gt;9216845717656874712980450562726202415567360565980794777111390850331644813674856981646960226192287360, 513637207677450246125760857023446893186481668075116373246321641937144993869266524849692790595738232, 196191955446197556957565929345772792668594307949581132632670453793550007197467505024573547039776939, 46314638123912707463692067318029823029991796402327083329291014906539951751195524576517845992591769, 17690617586682990180447203622188161240682337031027142006892310369574875779255058929007841461590953, 6757214636136263077649543548534660692055214690754342691385916202184675586569652210505678392181090, 1595161992684664972646689501703019021088600608282570556855039728226373625661856805487290962276456, 609297663643530892791951979990217206693894175329255046444641219473596270869815908465388209600595, 232730998245927705729166438267632598993081917705194582478883930194415186947590919908873666525329, 88895331094252224395547334812680590285351577786328700992010571109649289972956851261232789975392, 33954995036828967457475566170409171862972815653791520497147783134532682971279633874824703400847, 1892247019390521442608211077147886839616506438992322504018876947992022613217501281456451614651, 446698926797525733283994464723773897373051547730509482206718754667074636645528022516256487945, 170623807298553611905880623235491323624375649830112453507358412671675285005069415562415412537, 65172495098135102433647404982700073500075401759827878315356483347951218369680224170989749666, 24893677995851695395061591712608896875850555449371181438711037372178370103971256950553836461, 5876600217011727891986851402355662620898026272799849437157779835010586219504163589210317027, 2244661544603472032436332649584708114319787957314032873538930901437280496774780497748874337, 125090700579089545268174422433569433531336921195894847055310250098200676237081739043824861, 6971065820139782390806954219541689244276624212074373456653600330331675492690805039973161, 2662710205480735617346452022100755074809023407208374441801919604845563638678145849451440, 91708675472160090711036102616287632089318911882123915231537729562617689923506638302133, 35029596967131343602213497450232647402139968983372205851566400021802909132390757909314, 745648276861993189984204820755333242001144560869101973859680384188513887852280667477, 9809463517264670023038788649658295091956272699959366635620342487725314342549664567, 3746881652193013001948452031301618270087167924331813432662649918207032018665867029, 1431181439314368982806567444246559718305231073036073662367607266895781713447936520, 546662665750093946471250301438060884828525294776407554440171882480313121677942531, 129049549878268233256883381302815012467835672190109552534355121389997818506160385, 49292541820623609906583302538007088755326533087070104115801862234837985426429697, 7191684930184179482016276395611672639105248126232175323349533708710427892956421, 2746979206949941983182302875628764119171817307595766156998135811615145905740557, 648473825618649048121038413079524682351409714485519861708388359345126257210057, 58472848379039952684853851736901133239741266891456844557261755914039063645794, 22334640661774067356412331900038009953045351020683823507202893507476314037053, 1244666864935793005828156005589143096022236302705537193166716344690085611761, 475420437734698220747368027166749382927701417016557193662268716376935476241, 181594448268301656413948075911105052760867948344134387820089804440720816962, 16374361185569570355515148989381228747223756609038926650176124155306760699, 6254449428820551641549772190170184190608177514674331726439961915653414425, 1476475227036382503281437027911536541406625644706194668152438732346449273, 133133688169362819419341682354326791750874517270785300499298099495818696, 50852543833066829834000968538942350270948615962802847667687312219838755, 19423943329837670082661223262500259061971330617623242503763837163697569, 7419286156446180413982701248558426914965375890066879843604199271253952, 1751455877444438095408940282208383549115781784912085789506677971125378, 157928677948851033162880158208040021697730983590298819190379481318411, 60323387178125067141700354899227346590944200352359771993651057202793, 23041483585524168262220906489642018075101617466780496790573690289968, 8801063578447437644962364569698707634360652047981718378070013667111, 3361707149818144672666187219454104827980338677164658343636350711365, 1284057871006996373036197088663606849580363983512256652839038466984, 490466463202844446442404046536715720760753273372111614880764689587, 44225333398004061429732838340729878012027363723832270745251370289, 16892574194241670428824570378554538679120491007541580961500624834, 6452389184720949856740872794933738025334109298792472139250504213, 137347080577163115432025771710279131845700275212767467264610201, 32423247527351544763402471792982538876233052554697128188128597, 12384578529797304192493293627316781267732493780359086838016392, 690168906931029935139391829792095612517948949963798093315456, 38461794961234640015759308940939757590587318989278841661816, 14691098406862188148944207245954912110548093601382197697835, 5611500259351924431073312796924978741056961814867751431689, 2143402371193585144275731144820024112622791843221056597232, 119447720249892581203851665820676436622934188700177088360, 45624969256769882625644229676772632057353264935332782291, 6656593304481317393598839952151746590023553382130993248, 370959230771131880927453318055001997489772178180790104, 87571595343018854458033386304178158174356588264390370, 33449372971981195681356806732944396691005381570580873, 712011255569818855923257924200496343807632829750245, 271964099255182923543922814194423915162591622175362, 24522987531716273545293036474970821924473060471519, 3577855662560905981638959513147239988861837901112, 199387062373213542599493807777207997205533596336, 76159080909572301618801306271765994056795952743, 6867260041627791953052057353082063289320596021, 619220451666590135228675387863297874269396512, 236521166007575960984144537828161815236311727, 90343046356137747723758225621187571439538669, 21327100234463183349497947550385773274930109, 5034645418285014325766435419644478339818233, 173402521172797813159685037284371942044301, 25299086886458645685589389182743678652930, 9663391306290450775010025392525829059713, 1409869790947669143312035591975596518914, 538522340430300790495419781092981030533, 205697230343233228174223751303346572685, 18547707689471986212190138521399707760, 7084593923980518516849609894969925639, 244006547798191185585064349218729154, 93202207781383214849429075266681969, 35600075545958458963222876581316753, 13598018856492162040239554477268290, 5193981023518027157495786850488117, 1983924214061919432247806074196061, 757791618667731139247631372100066, 178890334785183168257455287891792, 16130531424904581415797907386349, 3807901929474025356630904134051, 555565404224292694404015791808, 131151201344081895336534324866, 659034621587630041982498215, 251728825683549488150424261, 96151855463018422468774568, 14028366653498915298923761, 3311648143516982017180081, 781774079430987230203437, 298611126818977066918552, 70492524767089125814114, 16641027750620563662096, 2427893228399975082453, 573147844013817084101, 12200160415121876738, 1100087778366101931, 259695496911122585, 99194853094755497, 37889062373143906, 14472334024676221, 3416454622906707, 806515533049393, 308061521170129, 117669030460994, 2504730781961, 365435296162, 139583862445, 4807526976, 701408733, 165580141, 63245986, 14930352, 121393, 4181, 987, 233, 55, 3]

real    0m0.017s
user    0m0.011s
sys 0m0.006s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Celebrity list
&lt;/h2&gt;

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

&lt;p&gt;You are given a binary matrix (&lt;code&gt;m × n&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Write a script to find the celebrity, return -1 when none found. A celebrity is someone, everyone knows and knows nobody.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;For input from the command line, I take a JSON string, and convert it to a list of lists of integers (arrays in Perl). The first thing I do is check that the matrix is valid (each row is the same length). Even though the task suggests that &lt;code&gt;m&lt;/code&gt; and &lt;code&gt;n&lt;/code&gt; could be different values, it makes no sense if it is not square, so I check this as well.&lt;/p&gt;

&lt;p&gt;I then have a loop with the index called &lt;code&gt;row_idx&lt;/code&gt; and &lt;code&gt;row&lt;/code&gt; as the row from the matrix. If this row has any &lt;code&gt;1&lt;/code&gt; (meaning they know someone), I skip to the next row.&lt;/p&gt;

&lt;p&gt;I then check that all other people know this person (column &lt;code&gt;row_idx&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt;) or is the person themselves (&lt;code&gt;row_idx == col_idx&lt;/code&gt;). If they are, I return the current &lt;code&gt;row_idx&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;If the list is exhausted, I return &lt;code&gt;-1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_celebrity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;row_length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matrix&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="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;row_length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;All rows must have the same length&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row_idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;is_celebrity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;col_idx&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;row_idx&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;matrix&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;col_idx&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;row_idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;col_idx&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row_length&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="n"&gt;is_celebrity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;row_idx&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"[[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], [1, 0, 0, 0]]"&lt;/span&gt;
&lt;span class="nt"&gt;-1&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"[[0, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0]]"&lt;/span&gt;
0

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"[[0, 1, 0, 1, 0, 1], [1, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 0], [1, 0, 1, 1, 0, 0]]"&lt;/span&gt;
3

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"[[0, 1, 1, 0], [1, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0]]"&lt;/span&gt;
&lt;span class="nt"&gt;-1&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"[[0, 0, 1, 1], [1, 0, 0, 0], [1, 1, 0, 1], [1, 1, 0, 0]]"&lt;/span&gt;
&lt;span class="nt"&gt;-1&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"[[0, 1, 0, 1, 0, 1], [1, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 0], [1, 0, 1, 1, 0, 0]]"&lt;/span&gt;
3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Weekly Challenge: Padding and sorting</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Mon, 09 Feb 2026 06:53:44 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challenge-padding-and-sorting-3oj8</link>
      <guid>https://forem.com/simongreennet/weekly-challenge-padding-and-sorting-3oj8</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 360
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-360/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-360/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Text Justifier
&lt;/h2&gt;

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

&lt;p&gt;You are given a string and a width.&lt;/p&gt;

&lt;p&gt;Write a script to return the string that centers the text within that width using asterisks &lt;code&gt;*&lt;/code&gt; as padding.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;If the &lt;code&gt;input_string&lt;/code&gt; length is larger or equal to the &lt;code&gt;width&lt;/code&gt; variable, I simply return the original string, as no padding is required.&lt;/p&gt;

&lt;p&gt;I then create a variable called &lt;code&gt;asterisks&lt;/code&gt; which is half the difference in length. Finally, I use the &lt;code&gt;floor&lt;/code&gt; and &lt;code&gt;ceil&lt;/code&gt; function to add the required number of asterisks. Doing this way ensure that if there is an odd number of asterisks required, the right side will have the additional asterisk.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;floor&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;text_justifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;string_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;string_len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;

    &lt;span class="n"&gt;asterisks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;string_len&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="n"&gt;output_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asterisks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asterisks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output_string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Perl solution follows the same logic. The &lt;code&gt;floor&lt;/code&gt; and &lt;code&gt;ceil&lt;/code&gt; functions come from the &lt;a href="https://perldoc.perl.org/POSIX" rel="noopener noreferrer"&gt;POSIX&lt;/a&gt; module.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py Hi 5
&lt;span class="k"&gt;*&lt;/span&gt;Hi&lt;span class="k"&gt;**&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py Code 10
&lt;span class="k"&gt;***&lt;/span&gt;Code&lt;span class="k"&gt;***&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py Hello 9
&lt;span class="k"&gt;**&lt;/span&gt;Hello&lt;span class="k"&gt;**&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py Perl 4
Perl

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py A 7
&lt;span class="k"&gt;***&lt;/span&gt;A&lt;span class="k"&gt;***&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;""&lt;/span&gt; 5
&lt;span class="k"&gt;*****&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Word Sorter
&lt;/h2&gt;

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

&lt;p&gt;You are give a sentence. Write a script to order words in the given sentence alphabetically but keeps the words themselves unchanged.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This can be achieved as a one-liner in both Python and Perl.&lt;/p&gt;

&lt;p&gt;The Python solution is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;word_sorter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breaking this down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sentence.split()&lt;/code&gt; will split the original sentence into a list of strings. The separator is one or more white space characters.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sorted(..., key=lambda x: x.lower())&lt;/code&gt; will sort the list alphabetically in a case insensitive manner.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;join(" ", ...)&lt;/code&gt; will turn the list into a string, separated by a single space.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Perl solution uses the same logic, but a slightly different syntax.&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;main&lt;/span&gt; &lt;span class="p"&gt;($str) {&lt;/span&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="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;sort&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;$a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;cmp&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;$b&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;/\s+/&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"The quick brown fox"&lt;/span&gt;
brown fox quick The

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"Hello    World!   How   are you?"&lt;/span&gt;
are Hello How World! you?

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"Hello"&lt;/span&gt;
Hello

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"Hello, World! How are you?"&lt;/span&gt;
are Hello, How World! you?

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py &lt;span class="s2"&gt;"I have 2 apples and 3 bananas!"&lt;/span&gt;
2 3 and apples bananas! have I
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Weekly Challenge: Digital reduction</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Mon, 02 Feb 2026 07:10:55 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challenge-digital-reduction-1aci</link>
      <guid>https://forem.com/simongreennet/weekly-challenge-digital-reduction-1aci</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 359
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-359/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-359/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Digital Root
&lt;/h2&gt;

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

&lt;p&gt;You are given a positive integer, $int.&lt;/p&gt;

&lt;p&gt;Write a function that calculates the additive persistence of a positive integer and also return the digital root.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Digital root is the recursive sum of all digits in a number until a single digit is obtained.&lt;/li&gt;
&lt;li&gt;Additive persistence is the number of times you need to sum the digits to reach a single digit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;Starting this week, I'm going to turn off VS Code Copilot when completing the challenge. As AI takes over the task of code completion, it's still a good exercise to do things by hand so as I don't depend on it.&lt;/p&gt;

&lt;p&gt;For this tasks, I create two variables. The first is called &lt;code&gt;persistence&lt;/code&gt; and starts at &lt;code&gt;0&lt;/code&gt;. The second variable is called &lt;code&gt;digital_root&lt;/code&gt; and starts with the supplied integer. This is called &lt;code&gt;number&lt;/code&gt; in Python, as &lt;code&gt;int&lt;/code&gt; is a reserved word.&lt;/p&gt;

&lt;p&gt;I then have a loop that continues until &lt;code&gt;digital_root&lt;/code&gt; is a single digit. Breaking down the line:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;str(digital_root)&lt;/code&gt; will convert the &lt;code&gt;digital_root&lt;/code&gt; integer to a string&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;d for d in&lt;/code&gt; will convert each character to a single digit&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;map(int(...&lt;/code&gt; will convert the digit back to an integer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sum(...&lt;/code&gt; will add the single digit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also increment the &lt;code&gt;persistence&lt;/code&gt; value by one. I end by returning the two values. The &lt;code&gt;main&lt;/code&gt; function is responsible for displaying the text as per the examples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_digital_root&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;number&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="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You must provide a positive integer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;persistence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;digital_root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digital_root&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;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;digital_root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;digital_root&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
        &lt;span class="n"&gt;persistence&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;return&lt;/span&gt; &lt;span class="n"&gt;persistence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digital_root&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Perl solution follows the same logic. Perl doesn't make a distinction between string and integers (yes, there are some exceptions to this rule), but does require the &lt;a href="https://perldoc.perl.org/functions/split" rel="noopener noreferrer"&gt;split&lt;/a&gt; function to break the &lt;code&gt;digital_root&lt;/code&gt; value into individual digits.&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;List::&lt;/span&gt;&lt;span class="nv"&gt;Util&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sum&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;main&lt;/span&gt; &lt;span class="p"&gt;($int) {&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$persistence&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;$digital_root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$int&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Keep iterating until we have a single digital&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;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$digital_root&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;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;$digital_root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;sum&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;//&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$digital_root&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$persistence&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="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Persistence  = &lt;/span&gt;&lt;span class="si"&gt;$persistence&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;Digital Root = &lt;/span&gt;&lt;span class="si"&gt;$digital_root&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 38
Persistence  &lt;span class="o"&gt;=&lt;/span&gt; 2
Digital Root &lt;span class="o"&gt;=&lt;/span&gt; 2

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 7
Persistence  &lt;span class="o"&gt;=&lt;/span&gt; 0
Digital Root &lt;span class="o"&gt;=&lt;/span&gt; 7

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 999
Persistence  &lt;span class="o"&gt;=&lt;/span&gt; 2
Digital Root &lt;span class="o"&gt;=&lt;/span&gt; 9

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 1999999999
Persistence  &lt;span class="o"&gt;=&lt;/span&gt; 3
Digital Root &lt;span class="o"&gt;=&lt;/span&gt; 1

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py 101010
Persistence  &lt;span class="o"&gt;=&lt;/span&gt; 1
Digital Root &lt;span class="o"&gt;=&lt;/span&gt; 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: String Reduction
&lt;/h2&gt;

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

&lt;p&gt;You are given a word containing only alphabets.&lt;/p&gt;

&lt;p&gt;Write a function that repeatedly removes adjacent duplicate characters from a string until no adjacent duplicates remain and return the final word.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This is a duplicate (albeit slightly re-worded) of the first task in &lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-340/" rel="noopener noreferrer"&gt;week 340&lt;/a&gt;. Therefore I copy and pasted that code, and renamed the function. See my &lt;a href="https://dev.to/simongreennet/weekly-challenge-ascending-regex-to-remove-the-duplicates-2bd#task-1-duplicate-removals"&gt;original blog post&lt;/a&gt; on how this was solved.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py aabbccdd
&lt;span class="s2"&gt;""&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py abccba
&lt;span class="s2"&gt;""&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py abcdef
&lt;span class="s2"&gt;"abcdef"&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py aabbaeaccdd
&lt;span class="s2"&gt;"aea"&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py mississippi
&lt;span class="s2"&gt;"m"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>perl</category>
      <category>theweeklychallenge</category>
    </item>
    <item>
      <title>Weekly Challenge: Maximum Encryption</title>
      <dc:creator>Simon Green</dc:creator>
      <pubDate>Tue, 27 Jan 2026 06:49:48 +0000</pubDate>
      <link>https://forem.com/simongreennet/weekly-challenge-maximum-encryption-49a8</link>
      <guid>https://forem.com/simongreennet/weekly-challenge-maximum-encryption-49a8</guid>
      <description>&lt;h2&gt;
  
  
  Weekly Challenge 358
&lt;/h2&gt;

&lt;p&gt;Each week Mohammad S. Anwar sends out &lt;a href="https://theweeklychallenge.org/" rel="noopener noreferrer"&gt;The Weekly Challenge&lt;/a&gt;, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://theweeklychallenge.org/blog/perl-weekly-challenge-358/" rel="noopener noreferrer"&gt;Challenge&lt;/a&gt;, &lt;a href="https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-358/sgreen" rel="noopener noreferrer"&gt;My solutions&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Task 1: Max Str Value
&lt;/h2&gt;

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

&lt;p&gt;You are given an array of alphanumeric string, &lt;code&gt;@strings&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Write a script to find the max value of alphanumeric string in the given array. The numeric representation of the string, if it comprises of digits only otherwise length of the string.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;This task can be achieved in a single line in both Python and Perl, while still maintaining readability. For the Python solution I use list comprehension to convert each string into an integer (if it is all digits) or the length of string (if it isn't). This is wrapped around the &lt;a href="https://docs.python.org/3/library/functions.html#max" rel="noopener noreferrer"&gt;max&lt;/a&gt; function to return maximum (largest) of these values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;max_string_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_strings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isdigit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;input_strings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not to out-shinned, Perl can achieve similar functionality by using the &lt;a href="https://perldoc.perl.org/functions/map" rel="noopener noreferrer"&gt;map&lt;/a&gt; function, converting each string into its numeric representation or its length. Perl doesn't have a built-in &lt;code&gt;max&lt;/code&gt; function, but it is available from the &lt;a href="https://metacpan.org/pod/List::Util" rel="noopener noreferrer"&gt;List::Util&lt;/a&gt; package.&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;main&lt;/span&gt; &lt;span class="p"&gt;(@input_strings) {&lt;/span&gt;
    &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nv"&gt;max&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="sr"&gt;/^\d+$/&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="nb"&gt;length&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;@input_strings&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;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"123"&lt;/span&gt; &lt;span class="s2"&gt;"45"&lt;/span&gt; &lt;span class="s2"&gt;"6"&lt;/span&gt;
123

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"abc"&lt;/span&gt; &lt;span class="s2"&gt;"de"&lt;/span&gt; &lt;span class="s2"&gt;"fghi"&lt;/span&gt;
4

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"0012"&lt;/span&gt; &lt;span class="s2"&gt;"99"&lt;/span&gt; &lt;span class="s2"&gt;"a1b2c"&lt;/span&gt;
99

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"x"&lt;/span&gt; &lt;span class="s2"&gt;"10"&lt;/span&gt; &lt;span class="s2"&gt;"xyz"&lt;/span&gt; &lt;span class="s2"&gt;"007"&lt;/span&gt;
10

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-1.py &lt;span class="s2"&gt;"hello123"&lt;/span&gt; &lt;span class="s2"&gt;"2026"&lt;/span&gt; &lt;span class="s2"&gt;"perl"&lt;/span&gt;
2026
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Task 2: Encrypted String
&lt;/h2&gt;

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

&lt;p&gt;You are given a string &lt;code&gt;$str&lt;/code&gt; and an integer $int.&lt;/p&gt;

&lt;p&gt;Write a script to encrypt the string using the algorithm - for each character &lt;code&gt;$char&lt;/code&gt; in &lt;code&gt;$str&lt;/code&gt;, replace &lt;code&gt;$char&lt;/code&gt; with the &lt;code&gt;$int th&lt;/code&gt; character after &lt;code&gt;$char&lt;/code&gt; in the alphabet, wrapping if needed and return the encrypted string.&lt;/p&gt;

&lt;h3&gt;
  
  
  My solution
&lt;/h3&gt;

&lt;p&gt;For this task, I start by setting &lt;code&gt;$int&lt;/code&gt; (called &lt;code&gt;i&lt;/code&gt; in Python as &lt;code&gt;int&lt;/code&gt; is a reserved word) to be the modulus (remainder) of 26. If that value is &lt;code&gt;0&lt;/code&gt;, I return the original string as no encryption is required.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;encrypted_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&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;return&lt;/span&gt; &lt;span class="n"&gt;input_string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is creating a mapping table. I start with the variable &lt;code&gt;old_letters&lt;/code&gt; that has all the lower case letters of the English alphabet. I create a &lt;code&gt;new_letters&lt;/code&gt; string by slicing the &lt;code&gt;old_letters&lt;/code&gt; string at the appropriate point. I then double the length of each string by adding the upper case equivalent string. Finally, I use &lt;code&gt;dict(zip())&lt;/code&gt; to convert the strings to a dictionary where the key is the original letter and the value is the new letter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="n"&gt;old_letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ascii_lowercase&lt;/span&gt;
    &lt;span class="n"&gt;new_letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;old_letters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;old_letters&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;old_letters&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;old_letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;new_letters&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;new_letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;mapping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_letters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_letters&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final step is to loop through each character and use the &lt;code&gt;mapping&lt;/code&gt; dictionary to replace the letter, or use the original character if it is not found (numbers, spaces, punctuation characters, etc).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;input_string&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 code follows the same logic. It uses the splice method to create the &lt;code&gt;new_letters&lt;/code&gt; variable, and both &lt;code&gt;old_letters&lt;/code&gt; and &lt;code&gt;new_letters&lt;/code&gt; are arrays. The &lt;code&gt;mesh&lt;/code&gt; function also comes from the List::Util package. Perl will automatically convert a flat list to key/value pairs in the &lt;code&gt;mapping&lt;/code&gt; hash.&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;main&lt;/span&gt; &lt;span class="p"&gt;( $input_string, $i ) {&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;26&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;$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="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="nv"&gt;$input_string&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="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@old_letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@new_letters&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="s2"&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="s2"&gt;z&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;@new_letters&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;@new_letters&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;$i&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;@old_letters&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;uc&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@old_letters&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;@new_letters&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;uc&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@new_letters&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;%mapping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;mesh&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;@old_letters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="nv"&gt;@new_letters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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="nb"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$mapping&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="sr"&gt;//&lt;/span&gt; &lt;span class="vg"&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;$input_string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py abc 1
bcd

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py xyz 2
zab

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py abc 27
bcd

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py hello 5
mjqqt

&lt;span class="nv"&gt;$ &lt;/span&gt;./ch-2.py perl 26
perl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>perl</category>
      <category>python</category>
      <category>theweeklychallenge</category>
    </item>
  </channel>
</rss>
