Peter’s blog ✴ Week 386 ✴ 10 August 2026
THE WEEKLY CHALLENGE
Hitting the bases with recurring numbers
You are given a string representing a number, and an integer specifying the base of that representation. Write a function to convert this string to a decimal integer.
For bases greater than 10, use characters A-Z, a-z, + and / in that order.
Example 1 Input: $num = '101010', $base = 2 Output: 42 Example 2 Input: $num = 'EEADEE', $base = 16 Output: 15642094 Example 3 Input: $num = '755', $base = 8 Output: 493 Example 4 Input: $num = '1BRJB', $base = 36 Output: 2228519 Example 5 Input: $num = '7MyqL', $base = 64 Output: 123456789
My algorithm is to process each digit, left to right,
multiply the result so far (or 1 if none) by $base, and add the value
of the current digit. And that's the answer.
There are a couple of necessary sanity checks: firstly that the
base is between 2 and 64 (because we have been given only 64
characters to use), and secondly that
the each character in the supplied number evaluates to no more
than $base - 1 - so eg for base 10, the maximum digit is 9.
I haven't dealt with negative integers or base 1 numbers; and
integers in large bases (eg 64) quickly exceed Perl's maximum
integer so you'd need Math::BigInt to handle those properly.
In week 386, Peter presents a neat, efficient, and very strong Perl design for the base conversion process. The blog post is remarkable because there is an insightful mention of the special cases, and all the edge cases are taken into account, for example, the digit limits and base limits, which makes it different from the others.
This review may cover either or both challenges for this week.
I am sorry that the 'Try it' feature is currently working very slowly or not at all owing to some issue with my web hosting provider.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge/386/1 use v5.26; # The Weekly Challenge - 2026-08-10 use utf8; # Week 386 - task 1 - Reverse base use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; use Encode; reverse_base('101010', 2); reverse_base('EEADEE', 16); reverse_base('755', 8); reverse_base('1BRJB', 36); reverse_base('7MyqL', 64); reverse_base('TheWeeklyChallenge', 62); reverse_base('', 44); reverse_base('11111', 1); reverse_base('181', 8); reverse_base('-', 10); sub reverse_base { my ($string, $base, $j, $c, %values, $decimal, $rest, $digit); # initialise ($string, $base) = @_; say qq[\nInput: \$number = '$string', \$base = $base]; unless ($base > 1 and $base < 65) { say qq[Output: base must be between 2 and 64]; return; } # build values table $j = 0; for $c ('0' .. '9', 'A' .. 'Z', 'a' .. 'z', '+', '/') { $values{$c} = $j ++; } # convert string to decimal $decimal = 0; while ($string ne '') { ($digit, $rest) = $string =~ m|^(.)(.*)$|g; if (not defined $values{$digit} or $values{$digit} >= $base) { say qq[Output: invalid digit '$digit']; return; } $decimal = $decimal * $base + $values{$digit}; $string = $rest; } say qq[Output: $decimal base 10]; }
17 lines of code
Input: $number = '101010', $base = 2 Output: 42 base 10 Input: $number = 'EEADEE', $base = 16 Output: 15642094 base 10 Input: $number = '755', $base = 8 Output: 493 base 10 Input: $number = '1BRJB', $base = 36 Output: 2228519 base 10 Input: $number = '7MyqL', $base = 64 Output: 123456789 base 10 Input: $number = 'TheWeeklyChallenge', $base = 62 Output: 8.77960529197082e+31 base 10 Input: $number = '', $base = 44 Output: 0 base 10 Input: $number = '11111', $base = 1 Output: base must be between 2 and 64 Input: $number = '181', $base = 8 Output: invalid digit '8' Input: $number = '-', $base = 10 Output: invalid digit '-'
Any content of this website which has been created by Peter Campbell Smith is in the public domain