Solving coin problems: Difference between revisions
→{{header|Perl}}: step 4: remove dead code, reorganize, reformat
SqrtNegInf (talk | contribs) (→{{header|Perl}}: step 3: cut down on copy/paste boiler-plate, streamline initialization, clarify need for MAXIMA) |
SqrtNegInf (talk | contribs) (→{{header|Perl}}: step 4: remove dead code, reorganize, reformat) |
||
Line 519:
);
my $decimal = qr/(?:[1-9][0-9]*\.?[0-9]*)|(?:0?\.[0-9]+)/;
while (<DATA>) {
chomp;
next if /^\s*$/ or /^\s*#.*$/; # skip blank and comment lines
my($count, $total) = (0, 0);
our @words = our @eqns = our @vars = our @types = ();
sub add_type {
push @vars, "v_$type: $value";
push @types, $type;
}
# Step 1: standardize language
s/-/ /g; # convert hyphens to spaces
$_ = lc($_); # convert to lower case
# tokenize sentence boundaries, punctuation, symbols
s/([\
s/([\.\?\!])$/ $1\n/g;
s/\$(.)/\$ $1/g; # prefix
s/(.)([\;\:\%',¢])/$1 $2/g; # suffix
# fractions/multipliers
s/half.dollars?/half_dollar/g;
s/\b(one )?half\b/0.5/g;
s/\btwice\b/two times/g;
# convert English number-names to numbers
foreach my $key (keys %nums) { s/\b$key\b/$nums{$key}/eg }
# remove plurals
s/
s/
# misc
s/dollar coin/dollar_coin/g;
s/(\d+) dollar\b/\$ $1/g;
s/((?:\d+ )*\d+)/sum(split(' ',$1))/eg;
# remove non-essential words
s/\b(the|a|to|of|i|is|that|it|on|you|this|for|but|with|are|have|be|at|or|was|so|if|out|not|he|she|they|has|do|did|does)\b\s*//g;
# Step 2: assign numeric values to terms
add_type('dollar_coin',100) if /dollar_coin/;
add_type('half_dollar',50) if /half_dollar/;
add_type('quarter',25) if /quarter/;
add_type('dime',10) if /dime/;
add_type('nickel',5) if /nickel/;
add_type('penny',1) if /penny/;
add_type($1, 100 * $1) while /\$ (\d+) bill/g;
# Step 3: determine algebraic relationships
while (/(
while (/($decimal) (?:times )?as many (\w+) as (\w+)/g) { push @eqns, "n_$2 = n_$3
while (/(\d+) more (\w+) than (\w+)/g) { push @eqns, "n_$2 = n_$3 + $1" }
while (/(\d+) less (\w+) than (\w+)/g) { push @eqns, "n_$2 = n_$3 - $1" }
while (/(\d+) less \$ (\d+) bill than \$ (\d+) bill/g) { push @eqns, "n_$2 = n_$3 - $1" }
if (/same number (\w+) , (\w+) (?:, )?and (\w+)/) {
push @eqns, "n_$1 = n_$2";
push @eqns, "n_$2 = n_$3";
}
if (/(\d+) (?:\w+ )*
$count = $1; push @vars, "count: $count"
}
if (/total (?:\w+ )*\$ ($decimal)/ or /valu(?:e|ing) \$ ($
$total = 100 * $1;
push @vars, "total: $total";
}
if (/total (?:\w+ )*
$total = $1;
push @vars, "total: $total";
}
# Step 4: tally final total value, coin count
# sum total, dot product of values and quantities
my $dot_product = join(' + ', map {"n_$_ * v_$_"} uniq @types);
# count of all coins, sum of counts of each coin type
# Step 5: prepare batch file for external processing, run 'MAXIMA', output results
printf "problem: %s\n", s/\n/ /gr; # condensed problem statement
my $maxima_vars = join("\$\n", uniq @vars);
my $maxima_eqns = '['. join(', ', @eqns) . ']';
my $maxima_find = '['. join(', ', map {"n_$_"} @types) . ']';
if (@eqns and @vars) {
my $
open my $script, '>', $maxima_script or die "Couldn't open temporary file: $!\n";
print $script <<~"END";
$maxima_vars\$
solve($maxima_eqns, $maxima_find);
END
close $script;
open my $maxima_output, "/opt/local/bin/maxima -q -b $maxima_script |" or die "Couldn't open maxima: $!\n";
while (<$maxima_output>) {
print "solution: $1\n" if /\(\%o\d+\)\s+\[\[([^\]]+)\]\]/; # only display solution
}
close $maxima_output;
unlink $maxima_script;
print $results "Couldn't deduce enough information to formulate equations.\n"
}
print $results "\n";
}
Line 711 ⟶ 649:
A small child has 6 more quarters than nickels. If the total amount of coins is $3.00, find the number of nickels and quarters the child has.
A
A person has twice as many dimes as she has pennies and three more nickels than pennies. If the total amount of the coins is $1.97, find the numbers of each type of coin the person has.
Line 762 ⟶ 700:
solution: n_quarter = 11, n_nickel = 5
problem:
solution: n_quarter = 11, n_nickel = 21
|