Peter’s blog ✴ Week 386 ✴ 10 August 2026
THE WEEKLY CHALLENGE
Hitting the bases with recurring numbers
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
Well, this one wasn't as easy as I thought!
After some experiments, I decided the best way was to
convert each supplied number to a standard format such as:
1
1.2
1.2(3)
1.2(34)
0.12(345)
These formats have the unbracketed and bracketed components reduced to their minimum length, and comply with normal practices such as not starting or finishing with a decimal point. The process for doing that is as follows:
1.234(3434) -> 1.234(34)
1.234(34) -> 1.2(34)
1.232(32) -> 1.(23)
1.23(9) -> 1.24
1.29(9) -> 1.30
1.99(9) -> 2
1.(9) -> 2
12.(0) -> 12
12.34(0) -> 12.34
123. -> 123
456.000 -> 456
.123 -> 0.123
.123(45) -> 0.123(45)
Then, the numbers are equal if their normalised forms are textually identical.
I have purposely coded this using more lines than strictly neccesary, so that the conversion process is transparent.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge/386/2 use v5.26; # The Weekly Challenge - 2026-08-10 use utf8; # Week 386 - task 2 - Rational numbers use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; use Encode; rational_numbers('0.(12)', '0.(121)'); rational_numbers('0.12(32)', '0.1(23)'); rational_numbers('0.1(234)', '0.12(342)'); rational_numbers('12.99(99)', '13'); rational_numbers('0.(123)', '.1(231)'); rational_numbers('0.000', '0'); rational_numbers('42', '41.9999999(9)'); rational_numbers('0.456(456)', '0.45645(645)'); sub rational_numbers { my (@r, $j, $num, $brac, $unbrac, $len, $half, $k, $mult, $substr, $last); # initialise @r = @_; say qq[\nInput: \$rat1 = $r[0], \$rat2 = $r[1]]; # canonicalise the numbers (see blog) for $j (0, 1) { $num = $r[$j]; # split into bracketed and unbracketed parts if ($num =~ m|(.*) \( (.*) \)|x) { ($unbrac, $brac) = ($1, $2); # shorten the bracketed part if possible $len = length($brac); $half = int($len / 2); $mult = 1; for $k (1 .. $half) { $mult = $len / $k; if ($mult == int($mult)) { $substr = substr($brac, 0, $k); if ($brac eq $substr x $mult) { $brac = $substr; last; } } } # shorten the unbracketed part if possible while ($unbrac =~ m|^(.*)$brac$|g) { $unbrac = $1; } while (1) { $last = substr($unbrac, -1); last unless $last =~ m|\d|; if ($brac =~ m|^(.*)$last(.*)$|) { $brac = $last . $2 . $1; $unbrac = substr($unbrac, 0, -1); } else { last; } } # if the bracketed part is (9) add 1 to the digit before if ($brac eq '9') { $unbrac =~ m|.*\.(\d*)|; $mult = 10 ** (length($1)); $unbrac = (qq[$unbrac] * $mult + 1) / $mult; $brac = ''; } # if the bracketed part is (0), delete it $num = $unbrac . ($brac ? qq[($brac)] : ''); } # if the number ends with '.' and any zeroes, delete them $num = $1 if $num =~ m|^(\d*)\.0*$|; # if the number starts with '.', precede it with '0' $num = qq[0$num] if $num =~ m|^\.|; $r[$j] = $num; } say qq[Output: ] . ($r[0] eq $r[1] ? qq[true - both are $r[0]] : qq[false - $r[0] and $r[1]]); }
40 lines of code
Input: $rat1 = 0.(12), $rat2 = 0.(121) Output: false - 0.(12) and 0.(121) Input: $rat1 = 0.12(32), $rat2 = 0.1(23) Output: true - both are 0.1(23) Input: $rat1 = 0.1(234), $rat2 = 0.12(342) Output: true - both are 0.1(234) Input: $rat1 = 12.99(99), $rat2 = 13 Output: true - both are 13 Input: $rat1 = 0.(123), $rat2 = .1(231) Output: true - both are 0.(123) Input: $rat1 = 0.000, $rat2 = 0 Output: true - both are 0 Input: $rat1 = 42, $rat2 = 41.9999999(9) Output: true - both are 42 Input: $rat1 = 0.456(456), $rat2 = 0.45645(645) Output: true - both are 0.(456)
Any content of this website which has been created by Peter Campbell Smith is in the public domain