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.
master
Jag Talon 2014-03-30 13:40:57 -04:00
parent 77fcd894f1
commit 51824d2766
2 changed files with 66 additions and 21 deletions

View File

@ -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
# - 2<sup>2</sup>
sub format_exp {
my $factor = shift;
my $result;
if($factor->[1] > 1) {
return "$factor->[0]^$factor->[1]", "$factor->[0]<sup>$factor->[1]</sup>";
}
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;

View File

@ -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 2<sup>3</sup> × 3<sup>2</sup>'),
'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 3<sup>2</sup> × 5'),
'optimus prime 45' => undef,
);