The Weekly Challenge 386

Reverse Base and Rational Numbers

Task 1: Reverse Base

Given a number string and a base (2 <= base <= 36), reverse the digits of the number string and compute its decimal value.

Example Output

Input: $str = "123", $base = 10 Output: 321 Input: $str = "101", $base = 2 Output: 5

Logic

Reverse the character string, parse each digit in the specified radix/base, and evaluate the resulting integer in base 10.

Perl Solution

ch-1.pl

sub reverse_base ( $str, $base ) { my $rev = reverse $str; my @digits = ( '0' .. '9', 'a' .. 'z' ); my %val = map { $digits[$_] => $_ } 0 .. $#digits; my $result = 0; for my $char ( split //, lc($rev) ) { die "Invalid digit '$char' for base $base" unless exists $val{$char} && $val{$char} < $base; $result = $result * $base + $val{$char}; } return $result; }

Python Solution

ch-1.py

def reverse_base(num_str: str, base: int) -> int: """Reverse digits of num_str and evaluate in base.""" rev_str = num_str[::-1] return int(rev_str, base)

Task 2: Rational Numbers

Compare two rational number representations including non-repeating and repeating decimal parts (e.g. 0.1(23)), return 1 if mathematically equal, 0 otherwise.

Example Output

Input: $rat1 = "0.1(23)", $rat2 = "0.12(32)" Output: 1 Input: $rat1 = "12.99(99)", $rat2 = "13." Output: 1

Logic

Parse the integer part, non-repeating fractional digits, and repeating digits into exact fractions using Math::BigRat in Perl and fractions.Fraction in Python, and test exact mathematical equality.

Perl Solution

ch-2.pl

sub parse_rational ($str) { if ( $str =~ /^(\d+)(?:\.(\d*)(?:\((\d+)\))?)?$/ ) { my $int_part = $1; my $non_rep_part = $2 // ''; my $rep_part = $3 // ''; my $val = Math::BigRat->new($int_part); if ( length($non_rep_part) > 0 || length($rep_part) > 0 ) { if ( length($rep_part) == 0 ) { $val += Math::BigRat->new( $non_rep_part . '/' . ( 10**length($non_rep_part) ) ); } else { my $len_non = length($non_rep_part); my $len_rep = length($rep_part); my $num = ( $non_rep_part . $rep_part ) - ( $non_rep_part || 0 ); my $den = ( ( 10**$len_rep ) - 1 ) * ( 10**$len_non ); $val += Math::BigRat->new("$num/$den"); } } return $val; } }

Python Solution

ch-2.py

def parse_rational(rat_str: str) -> Fraction: """Parse rational string like '0.1(23)' to Fraction.""" match = re.match(r"^(\d+)(?:\.(\d*)(?:\((\d+)\))?)?$", rat_str) if not match: raise ValueError(f"Invalid format: {rat_str}") int_part, non_rep, rep = match.groups() res = Fraction(int(int_part), 1) non_rep = non_rep or "" if not rep: if non_rep: res += Fraction(int(non_rep), 10 ** len(non_rep)) else: len_non = len(non_rep) len_rep = len(rep) all_digits = int(non_rep + rep) prefix_digits = int(non_rep) if non_rep else 0 num = all_digits - prefix_digits den = (10**len_rep - 1) * (10**len_non) res += Fraction(num, den) return res