perl logo Perl logo (Thanks to Olaf Alders)

The weekly challenge 386 - Task 2: Rational Numbers

  1 #!/usr/bin/env perl
  2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-386/#TASK2
  3 #
  4 # Task 2: Rational Numbers
  5 # ========================
  6 #
  7 # You are given two strings representing non-negative rational numbers.
  8 #
  9 # Write a script to return true if the two given rational numbers are same
 10 # otherwise false.
 11 #
 12 ## Example 1
 13 ##
 14 ## Input: $rat1 = "0.(12)"
 15 ##        $rat2 = "0.(121)"
 16 ## Output: false
 17 ##
 18 ## Expansion of "0.(12)"  = 0.12 12 12 12
 19 ## Expansion of "0.(121)" = 0.121 121 121
 20 #
 21 ## Example 2
 22 ##
 23 ## Input: $rat1 = "0.1(23)"
 24 ##        $rat2 = "0.12(32)"
 25 ## Output: true
 26 ##
 27 ## Expansion of "0.1(23)"  = 0.1 23 23 23
 28 ## Expansion of "0.12(32)" = 0.12 32 32 32
 29 #
 30 ## Example 3
 31 ##
 32 ## Input: $rat1 = "0.1(234)"
 33 ##        $rat2 = "0.12(342)"
 34 ## Output: true
 35 ##
 36 ## Expansion of "0.1(234)"  = 0.1 234 234 234
 37 ## Expansion of "0.12(342)" = 0.12 342 342 342
 38 #
 39 ## Example 4
 40 ##
 41 ## Input: $rat1 = "12.99(99)"
 42 ##        $rat2 = "13."
 43 ## Output: true
 44 #
 45 ## Example 5
 46 ##
 47 ## Input: $rat1 = "0.(123)"
 48 ##        $rat2 = "0.1(231)"
 49 ## Output: true
 50 #
 51 ############################################################
 52 ##
 53 ## discussion
 54 ##
 55 ############################################################
 56 #
 57 # We know that a periodic part of n digits x1 x2 ... xn is the
 58 # same as (x1x2...xn)/99...9, with n 9s. So we just calculate
 59 # the number represented by both "$rat1" and "$rat2" by adding
 60 # - everything before the "." as an integer
 61 # - everything after the "." before starting the periodic just
 62 #   as is: digits x1 x2 ... xn turn into x1x2...xn / 10^m, where
 63 #   m is the amount of digits found in the number
 64 # - the periodic part is (x1x2...xn)/99...9, with n 9s, but also
 65 #   divided by 10^m from the digits before the periodic part
 66 # Once we calculated both numbers this way, we can simply compare
 67 # them.
 68 
 69 use v5.36;
 70 
 71 rational_numbers( "0.(12)", "0.(121)" );
 72 rational_numbers( "0.1(23)", "0.12(32)" );
 73 rational_numbers( "0.1(234)", "0.12(342)" );
 74 rational_numbers( "12.99(99)", "13." );
 75 rational_numbers( "0.(123)", "0.1(231)" );
 76 
 77 sub rational_numbers($rat1, $rat2) {
 78     say "Input: $rat1, $rat2";
 79     my $r1 = calculate($rat1);
 80     my $r2 = calculate($rat2);
 81     if($r1 == $r2) {
 82         say "Output: true";
 83     } else {
 84         say "Output: false";
 85     }
 86 }
 87 
 88 sub calculate($num) {
 89     my ($predot, $postdot) = split /\./, $num;
 90     return $predot + 0.0 unless $postdot;
 91     if($postdot =~ m/\(/) {
 92         my ($preperiodic, $periodic) = split /\(/, $postdot;
 93         $periodic =~ s/\)$//;
 94         my $periodic_length = length($periodic);
 95         my $periodic_part = '9'x$periodic_length;
 96         my $preperiodic_length = length($preperiodic);
 97         if($preperiodic_length > 0) {
 98             return $predot + ($preperiodic / (10 ** $preperiodic_length)) +
 99                 ( $periodic / $periodic_part / (10 ** $preperiodic_length) );
100         } else {
101             return $predot + ( $periodic / $periodic_part );
102         }
103     } else {
104         return $num;
105     }
106 }