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)

/;

Written on August 10, 2026