Perl Weekly Challenge 386.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 386.
Task 1: Reverse Base
Submitted by: Mohammad Sajid Anwar
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 an 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

I start from N=0. Then, for every digit D, starting from
the most significant, I update
N=N*B+D, where B is the base. This yields a 2-liner.
Examples
perl -E '
@d=(0..9,"A".."Z","a".."z","+","/");$v{$d[$_]}=$_ for 0..@d-1;for
my($N,$B)(@ARGV){$r=0;$r=$r*$B+$v{$_} for split "",$N; say "$N, $B -> $r"}
' 101010 2 EEADEE 16 755 8 1BRJB 36 7MyqL 64
Results:
101010, 2 -> 42
EEADEE, 16 -> 15642094
755, 8 -> 493
1BRJB, 36 -> 2228519
7MyqL, 64 -> 123456789
The full code is:
1 # Perl weekly challenge 386
2 # Task 1: Reverse Base
3 #
4 # See https://wlmb.github.io/2026/08/10/PWC386/#task-1-reverse-base
5 use v5.36;
6 use feature qw(try);
7 die <<~"FIN" unless @ARGV and @ARGV%2==0;
8 Usage: $0 N0 B0 N1 B1...
9 to convert the number Ni from the base Bi to base 10.
10 FIN
11 my @digits=(0..9,"A".."Z","a".."z","+","/");
12 my %to_decimal;
13 $to_decimal{$digits[$_]}=$_ for 0..@digits-1;
14
15 for my($num, $base)(@ARGV){
16 try {
17 die "Base should be a positive integer > 1: $base"
18 unless $base=~/^\d+$/ && $base > 1;
19 die "I can't handle bases larger than 64: $base"
20 unless $base <=64;
21 my $result = 0;
22 for(split "", $num){
23 die "Undefined digit: $_" unless defined(my $dec=$to_decimal{$_});
24 die "Undefined digit in base $base: $_" unless $dec < $base;
25 $result = $result*$base+$dec;
26 }
27 say "Num.= $num, base=$base -> $result";
28 }
29 catch($e){warn $e;}
30 }
Example:
./ch-1.pl 101010 2 EEADEE 16 755 8 1BRJB 36 7MyqL 64
Results:
Num.= 101010, base=2 -> 42
Num.= EEADEE, base=16 -> 15642094
Num.= 755, base=8 -> 493
Num.= 1BRJB, base=36 -> 2228519
Num.= 7MyqL, base=64 -> 123456789
Task 2: Rational Numbers
Submitted by: Mohammad Sajid Anwar
You are given two strings representing non-negative rational
numbers.
Write a script to return true if the two given rational
numbers are same otherwise false.
Example 1
Input: $rat1 = "0.(12)"
$rat2 = "0.(121)"
Output: false
Expansion of "0.(12)" = 0.12 12 12 12
Expansion of "0.(121)" = 0.121 121 121

Example 2
Input: $rat1 = "0.1(23)"
$rat2 = "0.12(32)"
Output: true
Expansion of "0.1(23)" = 0.1 23 23 23
Expansion of "0.12(32)" = 0.12 32 32 32

Example 3
Input: $rat1 = "0.1(234)"
$rat2 = "0.12(342)"
Output: true
Expansion of "0.1(234)" = 0.1 234 234 234
Expansion of "0.12(342)" = 0.12 342 342 342

Example 4
Input: $rat1 = "12.99(99)"
$rat2 = "13."
Output: true

Example 5
Input: $rat1 = "0.(123)"
$rat2 = "0.1(231)"
Output: true

Consider the rational number x=I.F(R) with integer part I,
fractional part F and recurring part R. Its meaning is
I+F 10^{-n}+10^{-n}R(10^{-m}+10^{-2m}+10^{-3m}...), where n
is the number of digits in F and m the number of digits
in R. The infinite sum is a geometrical sum
10-m+10-2m+10-3m…=1/(10m-1). Thus,
x=I+F/10^n+R/(10^n*(10^m-1)), which can finally be written
as x=N/D, where the numerator is N=(10^m-1)*(10^n*I+F)+R
and the denominator is D=10^n*(10^m-1). Two fractions
x=N_x/D_x and y=N_y/D_y are equal if and only if
N_x D_y==N_y D_x. I need an auxiliary function to get the
numerators and denominators of a list of numbers. The
results fit a three-liner.
Examples
perl -E '
sub f(@x){map{/(\d*).(\d*)(\((\d+)\))?/;($n,$m)=map{length}$2,$4;[(10**$m-1)*
(10**$n*$1+$2)+$4, 10**$n*(10**$m-1)]}@x}for my($x,$y)(@ARGV){($p,$q)=f($x,$y);
say "$x, $y -> ", $p->[0]*$q->[1]==$p->[1]*$q->[0]?"T":"F";}
' "0.(12)" "0.(121)" "0.1(23)" "0.12(32)" "0.1(234)" "0.12(342)" \
"12.99(99)" "13." "0.(123)" "0.1(231)"
Results:
0.(12), 0.(121) -> F
0.1(23), 0.12(32) -> T
0.1(234), 0.12(342) -> T
12.99(99), 13. -> T
0.(123), 0.1(231) -> T
10.1(23), 10.1(2323) -> T
The full code is:
1 # Perl weekly challenge 386
2 # Task 2: Rational Numbers
3 #
4 # See https://wlmb.github.io/2026/08/10/PWC386/#task-2-rational-numbers
5 use v5.36;
6 use feature qw(try);
7 sub to_num_den(@x){
8 map {
9 die "Not a rational: $_" unless /^(\d*).(\d*)(\((\d+)\))?$/;
10 my ($int, $frac, $rec) = map {$_||0} ($1, $2, $4);
11 my ($n, $m) = map {length} $2, $4;
12 [
13 (10**$m-1)*(10**$n*$int+$frac)+$rec,
14 10**$n*(10**$m-1)
15 ]
16 } @x
17 }
18
19 for my($r1,$r2)(@ARGV){
20 try {
21 my ($nd1, $nd2) = to_num_den($r1, $r2);
22 say $r1,
23 $nd1->[0]*$nd2->[1]==$nd1->[1]*$nd2->[0]?" == ":" != ",
24 $r2;
25 }
26 catch($e){warn $e;}
27 }
Example:
./ch-2.pl "0.(12)" "0.(121)" "0.1(23)" "0.12(32)" "0.1(234)" "0.12(342)" \
"12.99(99)" "13." "0.(123)" "0.1(231)"
Results:
0.(12) != 0.(121)
0.1(23) == 0.12(32)
0.1(234) == 0.12(342)
12.99(99) == 13.
0.(123) == 0.1(231)
/;