<?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: vinodk89</title>
    <description>The latest articles on Forem by vinodk89 (@vinodk89).</description>
    <link>https://forem.com/vinodk89</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%2F471249%2F838191e3-dcc3-4404-80fd-31269a35c388.png</url>
      <title>Forem: vinodk89</title>
      <link>https://forem.com/vinodk89</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/vinodk89"/>
    <language>en</language>
    <item>
      <title>Perl Weekly Challenge - 360: Perl Power: Two Tiny Scripts, Big Learning!</title>
      <dc:creator>vinodk89</dc:creator>
      <pubDate>Sun, 15 Feb 2026 11:09:05 +0000</pubDate>
      <link>https://forem.com/vinodk89/perl-weekly-challenge-360-perl-power-two-tiny-scripts-big-learning-2o61</link>
      <guid>https://forem.com/vinodk89/perl-weekly-challenge-360-perl-power-two-tiny-scripts-big-learning-2o61</guid>
      <description>&lt;p&gt;This week, I challenged myself to write small but meaningful Perl programs for Weekly Challenge — focusing on clean logic, edge cases, and test-driven validation.&lt;/p&gt;

&lt;p&gt;Sometimes, the simplest problems teach the strongest lessons.&lt;/p&gt;




&lt;h2&gt;
  
  
  Challenge 1: Text Justifier (Centering Text with Custom Padding)
&lt;/h2&gt;

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

&lt;p&gt;If the string length is greater than or equal to the width, return the string as-is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
Input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;("Hi", 5)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*Hi**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Implementation Highlights&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calculated total padding required.&lt;/li&gt;
&lt;li&gt;Split padding evenly left and right.&lt;/li&gt;
&lt;li&gt;Handled odd padding differences correctly.&lt;/li&gt;
&lt;li&gt;Covered edge cases like:

&lt;ul&gt;
&lt;li&gt;Empty string&lt;/li&gt;
&lt;li&gt;Width equal to string length&lt;/li&gt;
&lt;li&gt;Width smaller than string length&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my $pad_total = $width - $len;
my $left_pad = int($pad_total / 2);
my $right_pad = $pad_total - $left_pad;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures perfect centering even when padding is odd.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Importance of integer division in layout formatting&lt;/li&gt;
&lt;li&gt;Handling edge cases makes logic robust&lt;/li&gt;
&lt;li&gt;Writing test cases increases confidence immediately&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Challenge 2: Word Sorter (Alphabetical Word Sorting)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem Statement&lt;/strong&gt;&lt;br&gt;
Write a script to order words in the given sentence alphabetically but keeps the words themselves unchanged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;br&gt;
Input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"I have 2 apples and 3 bananas!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2 3 and apples bananas! have I
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Implementation Highlights&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Split words using whitespace regex&lt;/li&gt;
&lt;li&gt;Used Perl’s built-in sort&lt;/li&gt;
&lt;li&gt;Rejoined words with single spaces&lt;/li&gt;
&lt;li&gt;Managed multiple spaces correctly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Core Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my @words = split /\s+/, $str;
return join ' ', sort @words;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple. Elegant. Effective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perl’s sort is powerful and concise&lt;/li&gt;
&lt;li&gt;Regex-based splitting handles messy input cleanly&lt;/li&gt;
&lt;li&gt;Even small scripts benefit from structured testing&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>beginners</category>
      <category>coding</category>
      <category>learning</category>
      <category>perl</category>
    </item>
    <item>
      <title>Perl Weekly Challenge - 358: When Strings Become Numbers and Letters Start Shifting</title>
      <dc:creator>vinodk89</dc:creator>
      <pubDate>Sun, 01 Feb 2026 12:58:09 +0000</pubDate>
      <link>https://forem.com/vinodk89/perl-weekly-challenge-358-when-strings-become-numbers-and-letters-start-shifting-j84</link>
      <guid>https://forem.com/vinodk89/perl-weekly-challenge-358-when-strings-become-numbers-and-letters-start-shifting-j84</guid>
      <description>&lt;p&gt;One of the things I enjoy about the Weekly Perl Challenge (WPC) is how small problems often hide neat programming ideas.&lt;br&gt;
This week, I solved two challenges that look simple at first glance but beautifully showcase Perl’s strengths in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;String handling&lt;/li&gt;
&lt;li&gt;Regex usage&lt;/li&gt;
&lt;li&gt;Numeric/string duality&lt;/li&gt;
&lt;li&gt;ASCII manipulation&lt;/li&gt;
&lt;li&gt;Writing clean, testable code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s walk through both problems and the approach I used.&lt;/p&gt;


&lt;h2&gt;
  
  
  Challenge 1 — When Strings Become Numbers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;br&gt;
You are given a list of strings. For each string:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If it contains only digits, treat it as a number&lt;/li&gt;
&lt;li&gt;Otherwise, treat its length as its value
From these values, return the maximum.&lt;/li&gt;
&lt;/ul&gt;



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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strings&lt;/th&gt;
&lt;th&gt;Interpreted as&lt;/th&gt;
&lt;th&gt;Maximum&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"123", "45", "6"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;123, 45, 6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;123&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"abc", "de", "fghi"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3, 2, 4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"0012", "99", "a1b2c"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12, 99, 5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Observation&lt;/strong&gt;&lt;br&gt;
The heart of the problem is deciding:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is this string purely numeric, or not?”&lt;br&gt;
Perl makes this very easy with a simple regex.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use List::Util qw(max);

sub get_value {
    my $str = shift;

    return length($str) unless $str =~ /^\d+$/;
    return 0 + $str;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A tiny function does all the work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;^\d+$&lt;/code&gt; → checks if the string is fully numeric&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;length($str)&lt;/code&gt; → used when it’s not&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0 + $str&lt;/code&gt; → converts &lt;code&gt;"0012"&lt;/code&gt; into number &lt;code&gt;12&lt;/code&gt;
Then finding the maximum is trivial with map and max:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my $max = max(map { get_value($_) } @strings);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where Perl shines — &lt;code&gt;very little code, very clear intent&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Challenge 2 — Caesar Cipher (Letter Shifting)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;br&gt;
Implement a Caesar Cipher:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shift every lowercase letter by &lt;code&gt;N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Wrap around from &lt;code&gt;z&lt;/code&gt; to &lt;code&gt;a&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Leave other characters unchanged&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Shift&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"abc"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"bcd"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"xyz"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"zab"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"hello"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"mjqqt"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;"perl"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"perl"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Observation&lt;/strong&gt;&lt;br&gt;
This problem is a perfect use case for &lt;code&gt;ASCII arithmetic&lt;/code&gt;.&lt;br&gt;
Instead of thinking in terms of alphabets, think in numbers from 0 to 25.&lt;/p&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sub caesar_encrypt {
    my ($str, $int) = @_;
    $int %= 26;

    my $result = '';
    for my $char (split //, $str) {
        if ($char =~ /[a-z]/) {
            $result .= chr(
                (ord($char) - ord('a') + $int) % 26 + ord('a')
            );
        } else {
            $result .= $char;
        }
    }
    return $result;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This one line does the magic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chr((ord($char) - ord('a') + $int) % 26 + ord('a'))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Convert letter → ASCII (ord)&lt;/li&gt;
&lt;li&gt;Normalize to 0–25 range&lt;/li&gt;
&lt;li&gt;Add the shift&lt;/li&gt;
&lt;li&gt;Use modulo to wrap around&lt;/li&gt;
&lt;li&gt;Convert back to character (chr)&lt;/li&gt;
&lt;li&gt;No lookup tables. No special cases. Just math.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;Testing the Solutions&lt;/strong&gt;&lt;br&gt;
For both challenges, I wrote small test cases and printed PASS/FAIL results.&lt;br&gt;
This is a habit I’ve picked up from solving WPC regularly — even small scripts deserve tests.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Why I Loved These Challenges&lt;/strong&gt;&lt;br&gt;
These problems highlight why Perl is still a joy for problem solving:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regex makes validation trivial&lt;/li&gt;
&lt;li&gt;Numeric and string contexts work naturally&lt;/li&gt;
&lt;li&gt;Character manipulation is straightforward&lt;/li&gt;
&lt;li&gt;Functional tools like map make code concise&lt;/li&gt;
&lt;li&gt;Very expressive in very few lines&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;br&gt;
At first glance, these look like beginner problems.&lt;br&gt;
But they actually touch on important concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data interpretation&lt;/li&gt;
&lt;li&gt;Input validation&lt;/li&gt;
&lt;li&gt;ASCII math&lt;/li&gt;
&lt;li&gt;Writing minimal, readable logic
And Perl handles all of this elegantly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s what makes the &lt;code&gt;Weekly Perl Challenge&lt;/code&gt; so enjoyable — small puzzles, big learning.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>coding</category>
      <category>perl</category>
      <category>programming</category>
    </item>
    <item>
      <title>Perl Weekly Challenge: 357 - Kaprekar Steps &amp; Ordered Fractions (Perl)</title>
      <dc:creator>vinodk89</dc:creator>
      <pubDate>Sun, 25 Jan 2026 17:01:54 +0000</pubDate>
      <link>https://forem.com/vinodk89/perl-weekly-challenge-357-kaprekar-steps-ordered-fractions-perl-pn</link>
      <guid>https://forem.com/vinodk89/perl-weekly-challenge-357-kaprekar-steps-ordered-fractions-perl-pn</guid>
      <description>&lt;p&gt;This week’s Perl Weekly Challenge had two very interesting problems that look simple at first, but hide some beautiful logic underneath.&lt;/p&gt;

&lt;p&gt;I solved both tasks in Perl, and here’s a walkthrough of my approach and what I learned.&lt;/p&gt;




&lt;h4&gt;
  
  
  Task 1 — Kaprekar Steps
&lt;/h4&gt;

&lt;p&gt;We are given a 4-digit number and asked to repeatedly perform the following process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Arrange digits in descending order → form number A&lt;/li&gt;
&lt;li&gt;Arrange digits in ascending order → form number B&lt;/li&gt;
&lt;li&gt;Compute: &lt;code&gt;A - B&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Repeat with the result&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This process is known as Kaprekar’s routine for 4-digit numbers.&lt;/p&gt;

&lt;p&gt;A fascinating fact:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every valid 4-digit number (with at least two different digits) will reach 6174 in at most 7 steps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;6174 is called &lt;strong&gt;Kaprekar’s Constant&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;My Approach:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The key requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handle leading zeros (e.g., 1001 → "1001")&lt;/li&gt;
&lt;li&gt;Keep track of numbers already seen (to avoid infinite loops)&lt;/li&gt;
&lt;li&gt;Count the number of steps until 6174 is reached
I used:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sprintf("%04d", $n)&lt;/code&gt; to preserve leading zeros&lt;/li&gt;
&lt;li&gt;A hash &lt;code&gt;%seen&lt;/code&gt; to detect loops&lt;/li&gt;
&lt;li&gt;Sorting digits to build ascending and descending numbers&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Core Logic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my $s = sprintf("%04d", $n);
my @digits = split('', $s);
my @desc = sort { $b cmp $a } @digits;
my @asc  = sort { $a cmp $b } @digits;

my $desc_num = join('', @desc);
my $asc_num  = join('', @asc);

$n = $desc_num - $asc_num;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Showing Each Iteration&lt;/strong&gt;&lt;br&gt;
I also added a helper function to print each iteration like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3524 → 5432 - 2345 = 3087
3087 → 8730 - 0378 = 8352
8352 → 8532 - 2358 = 6174
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the program educational rather than just returning a number.&lt;/p&gt;




&lt;h4&gt;
  
  
  Task 2 — Ordered Unique Fractions**
&lt;/h4&gt;

&lt;p&gt;Given a number &lt;code&gt;N&lt;/code&gt;, generate all fractions:&lt;br&gt;
&lt;code&gt;num / den  where 1 ≤ num ≤ N and 1 ≤ den ≤ N&lt;/code&gt;&lt;br&gt;
Then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sort them by their numeric value&lt;/li&gt;
&lt;li&gt;Remove duplicate values&lt;/li&gt;
&lt;li&gt;Keep the fraction with the smallest numerator for equal values&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;My Approach&lt;/strong&gt;&lt;br&gt;
Step 1: Generate all possible fractions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for my $num (1..$n) {
    for my $den (1..$n) {
        push @fractions, [$num, $den];
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Sort by fraction value&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@fractions = sort {
    my $val_a = $a-&amp;gt;[0] / $a-&amp;gt;[1];
    my $val_b = $b-&amp;gt;[0] / $b-&amp;gt;[1];
    $val_a &amp;lt;=&amp;gt; $val_b || $a-&amp;gt;[0] &amp;lt;=&amp;gt; $b-&amp;gt;[0]
} @fractions;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: Remove duplicates intelligently&lt;br&gt;
Instead of reducing fractions (like 2/4 → 1/2), I tracked numeric values and kept the fraction with the smallest numerator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!exists $seen_values{$value} || $num &amp;lt; $seen_values{$value}) {
    $seen_values{$value} = $num;
    push @unique, [$num, $den];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Example Output (N = 4)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1/4, 1/3, 1/2, 2/3, 3/4, 1/1, 4/3, 3/2, 2/1, 3/1, 4/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fractions are ordered by value&lt;/li&gt;
&lt;li&gt;Duplicates like 2/2, 3/3, 4/4 don’t appear&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;2/4&lt;/code&gt; is replaced by &lt;code&gt;1/2&lt;/code&gt; because it has a smaller numerator&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;What I Learned This Week&lt;/strong&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  From Kaprekar problem
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Importance of preserving leading zeros&lt;/li&gt;
&lt;li&gt;Detecting infinite loops with a hash&lt;/li&gt;
&lt;li&gt;How a simple number routine hides deep mathematical beauty&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  From Fraction problem
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Sorting by computed values&lt;/li&gt;
&lt;li&gt;Eliminating duplicates without using GCD&lt;/li&gt;
&lt;li&gt;Writing clean data-structure driven Perl code using array references&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Both tasks looked straightforward, but required careful thinking about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Edge cases&lt;/li&gt;
&lt;li&gt;Ordering&lt;/li&gt;
&lt;li&gt;Data handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Perl made these tasks elegant to implement thanks to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Powerful sorting&lt;/li&gt;
&lt;li&gt;Flexible data structures&lt;/li&gt;
&lt;li&gt;String formatting utilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another fun and educational week with Perl Weekly Challenge!&lt;/p&gt;

&lt;p&gt;Happy hacking :)&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>perl</category>
      <category>programming</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Perl Weekly Challenge: 345</title>
      <dc:creator>vinodk89</dc:creator>
      <pubDate>Sat, 01 Nov 2025 12:40:10 +0000</pubDate>
      <link>https://forem.com/vinodk89/perl-weekly-challenge-345-2bld</link>
      <guid>https://forem.com/vinodk89/perl-weekly-challenge-345-2bld</guid>
      <description>&lt;p&gt;Both challenges provided this week (Challenge-345) an excellent opportunity to practice array manipulation and dynamic state tracking in Perl, using simple constructs like &lt;code&gt;for loops&lt;/code&gt;, &lt;code&gt;unshift&lt;/code&gt;, and effective boundary/state checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge 1: Peak Positions
&lt;/h2&gt;

&lt;p&gt;You are given an array of integers, &lt;code&gt;@ints&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Find all the peaks in the array, a peak is an element that is strictly greater than its left and right neighbours. Return the indices of all such peak positions.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;My Solution:&lt;/strong&gt;&lt;br&gt;
The core challenge is handling the boundary conditions—the first and last elements—which only have one neighbor.&lt;br&gt;
My strategy was to process the array from index &lt;em&gt;0&lt;/em&gt; to &lt;em&gt;N-1&lt;/em&gt; and define the "neighbors" for any given element &lt;code&gt;$ints[i]&lt;/code&gt; as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Left Neighbor (&lt;code&gt;$left&lt;/code&gt;):

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;$i&lt;/code&gt; is &lt;em&gt;0&lt;/em&gt; (the first element), the left neighbor is non-existent. To ensure the condition &lt;code&gt;$ints[i] &amp;gt; $left&lt;/code&gt; is always true, I set &lt;code&gt;$left = -1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Otherwise, &lt;code&gt;$left = $ints[$i-1]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Right Neighbor (&lt;code&gt;$right&lt;/code&gt;):

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;$i&lt;/code&gt; is &lt;em&gt;N-1&lt;/em&gt; (the last element), the right neighbor is non-existent. Again, I set &lt;code&gt;$right = -1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Otherwise, &lt;code&gt;$right = $ints[$i+1]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The final check is simply: &lt;code&gt;$ints[$i] &amp;gt; $left &amp;amp;&amp;amp; $ints[$i] &amp;gt; $right&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The solution uses a clean &lt;code&gt;for&lt;/code&gt; loop to iterate over the indices and the Perl range operator &lt;code&gt;0..$#ints&lt;/code&gt; for concise code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sub find_peaks {
    my @ints = @_;
    my @peaks;

    # Iterate through all indices
    for my $i (0..$#ints) {
        # Define the left neighbor, using -1 for the first element
        my $left  = ($i == 0 ) ? -1 : $ints[$i-1];

        # Define the right neighbor, using -1 for the last element
        my $right = ($i == $#ints) ? -1 : $ints[$i+1];

        # A peak is strictly greater than both its effective neighbors
        if ($ints[$i] &amp;gt; $left &amp;amp;&amp;amp; $ints[$i] &amp;gt; $right) {
            push @peaks, $i;
        }
    }
    return @peaks;
}

# Example: [2, 4, 6, 5, 3] -&amp;gt; Peak is 6 at index 2
# Output: (2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Challenge 2: Last Visitor
&lt;/h2&gt;

&lt;p&gt;You are given an integer array &lt;code&gt;@ints&lt;/code&gt; where each element is either a positive integer or &lt;code&gt;-1&lt;/code&gt;. &lt;br&gt;
We process the array from left to right while maintaining two lists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@seen (stores previously seen positive integers, newest at the front)
@ans (stores answers for each -1).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If $ints[i] is a positive number -&amp;gt; insert it at the front of @seen.
If $ints[i] is -1: 
    Let $x be how many -1s in a row we’ve seen before this one.
    If $x &amp;lt; len(@seen) -&amp;gt; append seen[x] to @ans
    Else -&amp;gt; append -1 to @ans
    At the end, return @ans.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Logic and State Management:
&lt;/h3&gt;

&lt;p&gt;This problem is all about maintaining and querying state.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;State Management&lt;/strong&gt; with &lt;code&gt;@seen&lt;/code&gt;: The requirement "newest at the front" is key. When a positive number comes in, we use &lt;code&gt;unshift&lt;/code&gt; to put it at the start of &lt;code&gt;@seen&lt;/code&gt;. This makes it behave like a &lt;strong&gt;stack&lt;/strong&gt;, but with array-based indexing (index 0 is newest, index 1 is next newest, and so on).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The&lt;/strong&gt; &lt;code&gt;-1&lt;/code&gt; &lt;strong&gt;Rule&lt;/strong&gt;: When we hit a &lt;code&gt;-1&lt;/code&gt;, we must look &lt;strong&gt;backward&lt;/strong&gt; to count the consecutive &lt;code&gt;-1&lt;/code&gt;s (&lt;code&gt;$x&lt;/code&gt;).

&lt;ul&gt;
&lt;li&gt;I used a small &lt;code&gt;while&lt;/code&gt; loop within the main loop to handle this lookback, starting from the element immediately before the current index &lt;code&gt;$i-1&lt;/code&gt;. The loop increments &lt;code&gt;$x&lt;/code&gt; as long as it finds &lt;code&gt;-1&lt;/code&gt;s.&lt;/li&gt;
&lt;li&gt;Once we have &lt;code&gt;$x&lt;/code&gt;, we check if it's a valid index: &lt;code&gt;$x &amp;lt; @seen&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;If it is, we retrieve the x-th newest element: &lt;code&gt;$seen[x]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If it's not (meaning we haven't seen enough positive numbers to satisfy the lookup), we append &lt;code&gt;-1&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The use of &lt;code&gt;unshift&lt;/code&gt; and direct array indexing in Perl makes the solution quite easy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sub process_ints {
    my @ints = @_;
    my @seen;  # Newest seen numbers are at the front (index 0)
    my @ans;

    for (my $i = 0; $i &amp;lt; @ints; $i++) {
        if ($ints[$i] == -1) {
            # 1. Calculate x: count of consecutive -1s before this one
            my $x = 0;
            my $j = $i - 1;
            while ($j &amp;gt;= 0 &amp;amp;&amp;amp; $ints[$j] == -1) {
                $x++;
                $j--;
            }

            # 2. Apply the lookup rule
            if ($x &amp;lt; @seen) {
                # $seen[0] is the newest (x=0)
                # $seen[1] is the next newest (x=1), etc.
                push @ans, $seen[$x]; 
            } else {
                push @ans, -1;
            }
        } else {
            # If positive number, insert at the front (newest)
            unshift @seen, $ints[$i];
        }
    }
    return @ans;
}

# Example: [2, -1, 4, -1, -1] 
# i=0: 2 -&amp;gt; @seen=(2)
# i=1: -1, x=0. x &amp;lt; @seen (0 &amp;lt; 1). @ans=(2).
# i=2: 4 -&amp;gt; @seen=(4, 2)
# i=3: -1, x=0. x &amp;lt; @seen (0 &amp;lt; 2). @ans=(2, 4).
# i=4: -1, x=1. x &amp;lt; @seen (1 &amp;lt; 2). @ans=(2, 4, 2).
# Output: (2, 4, 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>devchallenge</category>
      <category>algorithms</category>
      <category>showdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Perl Weekly Challenge: 344</title>
      <dc:creator>vinodk89</dc:creator>
      <pubDate>Sat, 25 Oct 2025 13:08:05 +0000</pubDate>
      <link>https://forem.com/vinodk89/perl-weekly-challenge-344-1god</link>
      <guid>https://forem.com/vinodk89/perl-weekly-challenge-344-1god</guid>
      <description>&lt;p&gt;Writing a blog for first time and this week's challenges provided a fantastic opportunity to explore different problem-solving strategies in Perl. I tried to solve one of the problem in Raku aswell :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenge 1: Add to Array Form
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;br&gt;
You are given an array of integers, &lt;code&gt;@ints&lt;/code&gt; and an integer, &lt;code&gt;$x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Write a script to add &lt;code&gt;$x&lt;/code&gt; to the integer in the &lt;code&gt;array-form&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The array form of an integer is a digit-by-digit representation stored as an array, where the most significant digit is at the 0th index.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;My Solution:&lt;/strong&gt;&lt;br&gt;
In Perl, when we use a list of digits in a string context, they are automatically concatenated. This allows us to convert the array-form number into a standard integer, perform the addition, and then convert the sum back into its array form in three concise steps.&lt;/p&gt;

&lt;p&gt;Here is the &lt;code&gt;add_to_array_form&lt;/code&gt; subroutine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sub add_to_array_form {
    my ($ints_ref, $x) = @_;

    # 1. Convert the array of digits into a single string/number.
    my $int_form = join('', @$ints_ref);

    # 2. Perform the arithmetic. Perl handles the large number arithmetic here.
    my $sum = $int_form + $x;

    # 3. Split the resulting sum back into an array of individual digits.
    my @result_array = split //, $sum;

    return @result_array;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This solution is highly efficient and perfectly illustrates Perl's strength in handling scalar contexts and type coercion.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vinod@vinod:~/my_folder/git/perlweeklychallenge-club/challenge-344/vinod-k/perl$ perl ch-1.pl 

Input Array: (1, 2, 3, 4)
Input X: 12
Output Array: (1, 2, 4, 6)

Input Array: (2, 7, 4)
Input X: 181
Output Array: (4, 5, 5)

Input Array: (9, 9, 9)
Input X: 1
Output Array: (1, 0, 0, 0)

Input Array: (1, 0, 0, 0, 0)
Input X: 9999
Output Array: (1, 9, 9, 9, 9)

Input Array: (0)
Input X: 1000
Output Array: (1, 0, 0, 0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Challenge 2: Build Target from Source Subarrays
&lt;/h2&gt;

&lt;p&gt;You are given two list: &lt;code&gt;@source&lt;/code&gt; and &lt;code&gt;@target&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Write a script to see if you can build the exact &lt;code&gt;@target&lt;/code&gt; by putting these smaller lists from &lt;code&gt;@source&lt;/code&gt; together in some order. You cannot break apart or change the order inside any of the smaller lists in &lt;code&gt;@source&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Solution:&lt;/strong&gt;&lt;br&gt;
They way used to solve this is - to convert the array sequences into strings and use the power of Perl's regular expression engine to perform prefix matching and consumption.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Convert the &lt;code&gt;$target&lt;/code&gt; array into a string (e.g., &lt;code&gt;"1234"&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;In a loop, iterate through all unused source subarrays.&lt;/li&gt;
&lt;li&gt;For each source subarray, check if it matches the current beginning of the target string.&lt;/li&gt;
&lt;li&gt;If a match is found, use the substitution operator (&lt;code&gt;s///&lt;/code&gt;) to remove the matched prefix from the target string, mark the source subarray as used, and continue to the next iteration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This logic is in the &lt;code&gt;can_build_target&lt;/code&gt; subroutine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sub can_build_target {
    my ($source_ref, $target_ref) = @_;
    my $target_string = join('', @$target_ref);

    my $source_count = scalar @$source_ref;
    my %used_source_indices = ();
    my @used_order = ();

    while (length $target_string) {
        my $match_found_in_cycle = 0;

        for my $i (0 .. $source_count - 1) {
            next if exists $used_source_indices{$i};

            my $sub_array_ref = $source_ref-&amp;gt;[$i];
            my $source_pattern = join('', @$sub_array_ref);

            # The core of the greedy match:
            # s/ ... / / checks for a match AND removes it if successful.
            # ^: Anchors the match to the start of the string.
            # \Q...\E: Quotes the pattern so it's treated literally (no regex metacharacters).
            if ($target_string =~ s/^\Q$source_pattern\E//) {
                $used_source_indices{$i} = 1;
                push @used_order, $sub_array_ref;
                $match_found_in_cycle = 1;
                last; # Move to the next prefix
            }
        }

        # If we couldn't match any source subarray, we fail.
        unless ($match_found_in_cycle) {
            return (0, []);
        }
    }
    return (1, \@used_order);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inod@vinod:~/my_folder/git/perlweeklychallenge-club/challenge-344/vinod-k/perl$ perl ch-2.pl 
Input: @source = ([2,3], [1], [4])
Input: @target = (1, 2, 3, 4)
Output: true
Use in the order: ([1], [2,3], [4])

Input: @source = ([1,3], [2,4])
Input: @target = (1, 2, 3, 4)
Output: false

Input: @source = ([9,1], [5,8], [2])
Input: @target = (5, 8, 2, 9, 1)
Output: true
Use in the order: ([1], [2,3], [4])

Input: @source = ([1], [3])
Input: @target = (1, 2, 3)
Output: false

Input: @source = ([7,4,6])
Input: @target = (7, 4, 6)
Output: true
Use in the order: ([7,4,6])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>algorithms</category>
      <category>devchallenge</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
