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:
- Arrange digits in descending order → form number A
- Arrange digits in ascending order → form number B
- Compute:
A - B - 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
%seento 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;
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
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:
- Sort them by their numeric value
- Remove duplicate values
- 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];
}
}
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;
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];
}
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
Notice:
- Fractions are ordered by value
- Duplicates like 2/2, 3/3, 4/4 don’t appear
-
2/4is replaced by1/2because 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)