From 51824d2766f87125585d722ddfaa404b118fc5d8 Mon Sep 17 00:00:00 2001 From: Jag Talon Date: Sun, 30 Mar 2014 13:40:57 -0400 Subject: [PATCH] PrimeFactors: Added new features: - Use `factor_exp` instead of `factor`. - Add commify to format the input. - Add exponents to the primes. It's much easier to read. --- lib/DDG/Goodie/PrimeFactors.pm | 69 +++++++++++++++++++++++++++------- t/PrimeFactors.t | 18 +++++---- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/lib/DDG/Goodie/PrimeFactors.pm b/lib/DDG/Goodie/PrimeFactors.pm index ba3c8a327..7b2dc8b8d 100644 --- a/lib/DDG/Goodie/PrimeFactors.pm +++ b/lib/DDG/Goodie/PrimeFactors.pm @@ -2,7 +2,8 @@ package DDG::Goodie::PrimeFactors; #Returns all the prime factors of the entered number use DDG::Goodie; -use Math::Prime::Util 'factor'; +use Math::Prime::Util 'factor_exp', 'is_prime'; +use utf8; zci answer_type => "prime_factors"; zci is_cached => 1; @@ -24,20 +25,62 @@ topics 'math'; category 'calculations'; attribution github => [ 'https://github.com/austinheimark', 'austin_heimark' ]; -handle remainder => sub { - return unless /^\d+$/; - my @factors = factor($_); +# This adds exponents to the prime numbers. +# It outputs both text and HTML: +# - 2^2 +# - 22 +sub format_exp { + my $factor = shift; - my $result; + if($factor->[1] > 1) { + return "$factor->[0]^$factor->[1]", "$factor->[0]$factor->[1]"; + } + return $factor->[0], $factor->[0]; +} + +# This goes through all the prime factors and formats them in an "n × m" format. +# It outputs both text and HTML. +sub format_prime { + my @factors = @_; + my @text_result = (); + my @html_result = (); + + foreach my $factor (@factors) { + my ($text, $html) = format_exp($factor); - # If it has only one factor then it is a prime. Except if it's 0 or 1. - if(@factors == 1 && $_ > 1) { - $result = "$_ is a prime number."; - } else { - $result = "The prime factors of $_ are " . join(', ', @factors) . '.'; - } - - return $result, 'html' => "$result"; + push(@text_result, $text); + push(@html_result, $html); + } + + return join(" × ", @text_result), join(" × ", @html_result); +} + +# This adds commas to the number. +# It converts 10000000 to 10,000,000. +# It was copied from http://perldoc.perl.org/perlfaq5.html#How-can-I-output-my-numbers-with-commas-added%3f +sub commify { + local $_ = shift; + 1 while s/^([-+]?\d+)(\d{3})/$1,$2/; + return $_; +} + +handle remainder => sub { + # Exit if it's not a digit. + # TODO: We should accept different number formats. + return unless /^\d+$/; + my @factors = factor_exp($_); + my $formatted = commify($_); + + # If it has only one factor then it is a prime. Except if it's 0 or 1. + my $result; + if(is_prime($_)) { + return "$formatted is a prime number.", html => "$formatted is a prime number."; + } else { + my ($text, $html) = format_prime(@factors); + my $intro = "The prime factorization of $formatted is"; + + return "$intro $text", html => "$intro $html"; + } }; 1; diff --git a/t/PrimeFactors.t b/t/PrimeFactors.t index 0e949b036..6fdc48ca5 100644 --- a/t/PrimeFactors.t +++ b/t/PrimeFactors.t @@ -2,6 +2,8 @@ use strict; use warnings; +use utf8; + use Test::More; use DDG::Test::Goodie; @@ -12,14 +14,14 @@ ddg_goodie_test( [qw( DDG::Goodie::PrimeFactors )], - '72 prime factors' => test_zci('The prime factors of 72 are 2, 2, 2, 3, 3.', - html => 'The prime factors of 72 are 2, 2, 2, 3, 3.'), - 'prime factors of 111' => test_zci('The prime factors of 111 are 3, 37.', - html => 'The prime factors of 111 are 3, 37.'), - 'prime factors of 30' => test_zci('The prime factors of 30 are 2, 3, 5.', - html => 'The prime factors of 30 are 2, 3, 5.'), - 'prime factorization of 45' => test_zci('The prime factors of 45 are 3, 3, 5.', - html => 'The prime factors of 45 are 3, 3, 5.'), + '72 prime factors' => test_zci('The prime factorization of 72 is 2^3 × 3^2', + html => 'The prime factorization of 72 is 23 × 32'), + 'prime factors of 111' => test_zci('The prime factorization of 111 is 3 × 37', + html => 'The prime factorization of 111 is 3 × 37'), + 'prime factors of 30' => test_zci('The prime factorization of 30 is 2 × 3 × 5', + html => 'The prime factorization of 30 is 2 × 3 × 5'), + 'prime factorization of 45' => test_zci('The prime factorization of 45 is 3^2 × 5', + html => 'The prime factorization of 45 is 32 × 5'), 'optimus prime 45' => undef, );