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 }