Peter’s blog ✴ Week 379 ✴ 22 June 2026
THE WEEKLY CHALLENGE
Reversing and curious numbers
You are given two integers, $base and $limit.
Write a script to find all Armstrong numbers in base $base that are less than $limit.
If raising each of the digits of a non-negative integer to the power of the total number of digits, then taking their sum, equals the original number, it is an Armstrong number.
Example 1 Input: $base = 10, $limit = 1000 Output: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407) Example 2 Input: $base = 7, $limit = 1000 Output: (0, 1, 2, 3, 4, 5, 6, 10, 25, 32, 45, 133, 134, 152, 250) Example 3 Input: $base = 16, $limit = 1000 Output: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 342, 371, 520, 584, 645)
Armstrong numbers were described by Michael Armstrong, an engineer and computer scientist at the University of Rochester.
So how do we compute them? To start with, although we are asked to
handle numbers with a base which might not be 10, I note that the supplied $limit
(and obviously $base), and the required answers are all expressed
in base 10.
We do however need to convert some numbers into and out of base $base,
and while I could have written a pair of subroutines to do that I
found Math::Int2Base, which does so very compactly, and have used
that.
The key statement in my solution is:
$sum += base2int(substr($jb, $_, 1), $base) ** $power
Here, $jb is the number under test ($j) expressed in base $base.
So for example, if $j == 10 and $base == 7 then
$jb == 13. The loop variable, $_, runs from zero to one
less than the length of $jb, and $power is the number of
characters in $jb.
And if the sum of powers as above equals $j we have found an Armstrong
number. They are relatively rare, although notably there are often a pair
which differ by 1, and 0 to $base - 1 are always included.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge use v5.26; # The Weekly Challenge - 2026-06-22 use utf8; # Week 379 - task 2 - Armstrong number use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; use Encode; use Math::Int2Base ('int2base', 'base2int'); armstrong_number(10, 10000); armstrong_number(7, 1000); armstrong_number(16, 1000); armstrong_number(9, 1000); sub armstrong_number { my ($base, $limit, $j, $jb, $power, $sum, $output); # initialise ($base, $limit) = @_; # loop over possibles for $j (0 .. $limit) { # get digits of $j in base $base and count them $jb = int2base($j, $base); $power = length($jb); # now sum digits ** $power $sum = 0; $sum += base2int(substr($jb, $_, 1), $base) ** $power for 0 .. $power - 1; # found one! $output .= qq[$j, ] if $sum == $j; } say qq[\nInput: \$base = $base, \$limit = $limit]; say qq[Output: ] . substr($output, 0, -2); }
12 lines of code
Input: $base = 10, $limit = 10000 Output: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474 Input: $base = 7, $limit = 1000 Output: 0, 1, 2, 3, 4, 5, 6, 10, 25, 32, 45, 133, 134, 152, 250 Input: $base = 16, $limit = 1000 Output: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 342, 371, 520, 584, 645 Input: $base = 9, $limit = 1000 Output: 0, 1, 2, 3, 4, 5, 6, 7, 8, 41, 50, 126, 127, 468, 469
Any content of this website which has been created by Peter Campbell Smith is in the public domain