Add factorial support. (#4331)

Support factorials. Fix - remove bug.

Fixed a couple of iafd data issues.
master
PJ Hampton 2017-07-03 19:02:33 +01:00 committed by Zaahir Moolla
parent cf799ad23b
commit 8e5cd3f431
2 changed files with 55 additions and 14 deletions

View File

@ -16,7 +16,7 @@ triggers query => $calc_regex;
triggers query => qr'^
(?: [0-9 () τ π e x × * + \- ÷ / \^ \$ £ \. \, _ ! = % ]+ |
\d+\%=?$ |
what\sis| calculat(e|or) | solve | math | log\sof |
what\sis| calculat(e|or) | solve | math | log\sof | fact(?:orial?)?(\s+of)? |
times | mult | multiply | divided\sby | plus | minus | cos | tau |
sin | tan | cotan | log | ln | exp | tanh |
sec | csc | squared | sqrt | \d+\s?mod(?:ulo)?\s?\d+ | gross | dozen | pi |
@ -65,7 +65,7 @@ my $network = qr#^$ip4_regex\s*/\s*(?:$up_to_32|$ip4_regex)\s*$#; # Lo
## prepares the query to interpreted by the calculator front-end
sub prepare_for_frontend {
my ($query, $style) = @_;
# Equals varies by output type.
$query =~ s/\=$//;
$query =~ s/(\d)[ _](\d)/$1$2/g; # Squeeze out spaces and underscores.
@ -110,7 +110,7 @@ sub rewriteQuery {
$text =~ s/times|mult/×/g;
$text =~ s/divided\s?by/÷/g;
$text =~ s/(cos|tau|τ|sin|tan|cotan|log|ln|exp|tanh|π|sec|csc|squared|sqrt|gross|dozen|pi|e|score)\s*\1/$1/g;
$text =~ s|([x × % + \- ÷ / \^ \$ £ \. \, _ =])\s*\1|$1|gx;
$text =~ s|([x × % + ÷ / \^ \$ £ \. \, _ =])\s*\1|$1|gx;
return $text;
}
@ -119,6 +119,13 @@ sub rewriteQuery {
# log of 5 --> log(5), log2 8 --> log(8,2), log321 --> log(321)
sub rewriteFunctions {
my ($query) = @_;
# Preprocesses modulo operations
$query =~ s/(\d+)(?:\s+?mod(?:ulo)?\s+?|\s+%\s+?)(\d+)/mod($1|$2)/;
# Preprocesses factorial operations
$query =~ s/fact\(?(\d+)\)?/$1!/;
$query =~ s/fact(?:orial?)?(?:\s+of)?\s+?(\(?\d+\)?)?/$1!/;
# Preprocesses Log/Ln
$query =~ s/log\sof\s(\d+)/log($1)/i;
@ -151,19 +158,19 @@ handle query => sub {
# We need to rewrite the functions for front-end consumption
$query = rewriteFunctions($query);
# throw out obvious non-calculations immediately
return if $query =~ qr/(\$(.+)?(?=£|€))|(£(.+)?(?=\$|€))|(€(.+)?(?=\$|£))/; # only let one currency type through
return if $req->query_lc =~ /^0x/i; # hex maybe?
return if $query =~ /\d+(?:X|x)\.?$/; # websites such as 1337X
return if $query =~ /^(?:\.\w+)/; # Probably looking at file extensions
return if $query =~ $network; # Probably want to talk about addresses, not calculations.
return if $query =~ m/^(\+?\d{1,2}(\s|-)?|\(\d{2})?\(?\d{3,4}\)?(\s|-)?\d{3}(\s|-)?\d{3,4}(\s?x\d+)?$/; # Probably are searching for a phone number, not making a calculation
return if $query =~ m/(\d+)\s+(\d+)/; # if spaces between numbers then bail
return if $query =~ m/^\)|\($/; # shouldn't open with a closing brace or finish with an opening brace
# some shallow preprocessing of the query
$query =~ s/(\d+)\s+%\s?(\d+)/$1mod$2/;
$query =~ s/^(?:what is|calculat(e|or)|solve|math)//i;
$query =~ s/\s//g;
# return based on the query type
return unless $query =~ m/[0-9τπe]|tau|pi/;
return if $query =~ $no_start_ops; # don't trigger with illegal operator at start
@ -188,7 +195,7 @@ handle query => sub {
$query =~ s#$name#$operation#xig; # We want these ones to show later.
}
return if ($tmp_expr eq $query) && ($query !~ /\de|cos|tan|sin|log|ln|mod|modulo/i); # If it didn't get spaced out, there are no operations to be done.
return if ($tmp_expr eq $query) && ($query !~ /\de|fact|cos|tan|sin|log|ln|mod|!/i); # If it didn't get spaced out, there are no operations to be done.
# Now sub in constants
while (my ($name, $constant) = each %named_constants) {
@ -199,6 +206,7 @@ handle query => sub {
return unless $style;
my $spaced_query = prepare_for_frontend($query, $style);
return if scalar(split(" ", $spaced_query)) < 2 && ($spaced_query !~ /^(fact|csc|sec|sqrt|cos|tan|sin|log|ln|mod|modulo|\d+\!$)/i);
return '', structured_answer => {
data => {

View File

@ -87,9 +87,6 @@ ddg_goodie_test(
'tanh(1)' => build_test(
'tanh(1)'
),
'cotan(1)' => build_test(
'cotan(1)'
),
'sin(1)' => build_test(
'sin(1)'
),
@ -334,10 +331,10 @@ ddg_goodie_test(
'$10.80 + 44'
),
'5 modulo 13' => build_test(
'5modulo13'
'mod(5,13)'
),
'5 % 13 + 5' => build_test(
'5mod13 + 5'
'mod(5,13) + 5'
),
'log(10)' => build_test(
'log(10)'
@ -372,6 +369,33 @@ ddg_goodie_test(
'log of 99 / 3' => build_test(
'log(99) / 3'
),
'factorial of 88' => build_test(
'88!'
),
'factorial 77 + 32' => build_test(
'77! + 32'
),
'8 * factorial of 77 + 32' => build_test(
'8 * 77! + 32'
),
'8 * fact of 77 + 32' => build_test(
'8 * 77! + 32'
),
'8 * fact(77) + 32' => build_test(
'8 * 77! + 32'
),
'8 * fact77 + 32' => build_test(
'8 * 77! + 32'
),
'8 * fact77 + 32' => build_test(
'8 * 77! + 32'
),
'fact(20)' => build_test(
'20!'
),
'fact 20' => build_test(
'20!'
),
'1432 / 28 2' => undef,
'5 + 88 2' => undef,
'14 8 - 22' => undef,
@ -445,8 +469,17 @@ ddg_goodie_test(
'12+5t%' => undef,
'2002 honda civic ex rim and lug size' => undef,
'2003 xc90 traction' => undef,
'123netflix' => undef
'123netflix' => undef,
'1337X' => undef,
'1337X.' => undef,
'1337X.' => undef,
'706007X' => undef,
'etan' => undef,
'.exe' => undef,
'.elxs' => undef,
'.gif' => undef,
'e.png' => undef,
')1108278829' => undef,
);
done_testing;