DEV Community

vinodk89
vinodk89

Posted on

Perl Weekly Challenge: 357 - Kaprekar Steps & Ordered Fractions (Perl)

This week’s Perl Weekly Challenge had two very interesting problems that look simple at first, but hide some beautiful logic underneath.

I solved both tasks in Perl, and here’s a walkthrough of my approach and what I learned.


Task 1 — Kaprekar Steps

We are given a 4-digit number and asked to repeatedly perform the following process:

  1. Arrange digits in descending order → form number A
  2. Arrange digits in ascending order → form number B
  3. Compute: A - B
  4. Repeat with the result

This process is known as Kaprekar’s routine for 4-digit numbers.

A fascinating fact:

Every valid 4-digit number (with at least two different digits) will reach 6174 in at most 7 steps.

6174 is called Kaprekar’s Constant.


My Approach:

The key requirements:

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

Core Logic

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;
Enter fullscreen mode Exit fullscreen mode

Showing Each Iteration
I also added a helper function to print each iteration like:

3524 → 5432 - 2345 = 3087
3087 → 8730 - 0378 = 8352
8352 → 8532 - 2358 = 6174
Enter fullscreen mode Exit fullscreen mode

This makes the program educational rather than just returning a number.


Task 2 — Ordered Unique Fractions**

Given a number N, generate all fractions:
num / den where 1 ≤ num ≤ N and 1 ≤ den ≤ N
Then:

  1. Sort them by their numeric value
  2. Remove duplicate values
  3. Keep the fraction with the smallest numerator for equal values

My Approach
Step 1: Generate all possible fractions

for my $num (1..$n) {
    for my $den (1..$n) {
        push @fractions, [$num, $den];
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Sort by fraction value

@fractions = sort {
    my $val_a = $a->[0] / $a->[1];
    my $val_b = $b->[0] / $b->[1];
    $val_a <=> $val_b || $a->[0] <=> $b->[0]
} @fractions;
Enter fullscreen mode Exit fullscreen mode

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

if (!exists $seen_values{$value} || $num < $seen_values{$value}) {
    $seen_values{$value} = $num;
    push @unique, [$num, $den];
}
Enter fullscreen mode Exit fullscreen mode

Example Output (N = 4)

1/4, 1/3, 1/2, 2/3, 3/4, 1/1, 4/3, 3/2, 2/1, 3/1, 4/1
Enter fullscreen mode Exit fullscreen mode

Notice:

  • Fractions are ordered by value
  • Duplicates like 2/2, 3/3, 4/4 don’t appear
  • 2/4 is replaced by 1/2 because it has a smaller numerator

What I Learned This Week

From Kaprekar problem
  • Importance of preserving leading zeros
  • Detecting infinite loops with a hash
  • How a simple number routine hides deep mathematical beauty
From Fraction problem
  • Sorting by computed values
  • Eliminating duplicates without using GCD
  • Writing clean data-structure driven Perl code using array references

Conclusion

Both tasks looked straightforward, but required careful thinking about:

  • Edge cases
  • Ordering
  • Data handling

Perl made these tasks elegant to implement thanks to:

  • Powerful sorting
  • Flexible data structures
  • String formatting utilities

Another fun and educational week with Perl Weekly Challenge!

Happy hacking :)

Top comments (0)