loadMacros("parserImplicitPlane.pl");
Context("ImplicitPlane")->variables->are(x=>"Real",y=>"Real");
$L = ImplicitPlane("4x + 5y = 2");
BEGIN_TEXT
\(\{$L->TeX\}\) is \{ans_rule(20)\}
END_TEXT
Context()->flags->set(tolerance=>.0001, tolType=>"absolute");
sub notInteger {
my $n = shift; my $N = floor($n->value);
return $n != $N; # uses tolerance and tolType set above
}
$integerCoefficients = sub {
my $ans = shift;
if ($ans->{ans_message} eq "" && !$ans->{isPreview}) {
my $student = $ans->{student_formula}{tree};
my $L = Formula($student->{lop}) - Formula($student->{rop});
my $C = $L->eval(x=>0, y=>0);
my $B = $L->eval(x=>0, y=>1) - $C;
my $A = $L->eval(x=>1, y=>0) - $C;
if (notInteger($A) || notInteger($B) || notInteger($C)) {
$ans->score(0);
$ans->{ans_message} = "Your coefficients should be integers";
}
}
return $ans;
};
ANS($L->cmp->withPostFilter($integerCoefficients));
Here, we set up an ImplicitPlane context with two variables (so the "plane" is really a line), then create the line and the text of the problem. The rest of the code is for checking the answer. The notInteger
function checks to see if a MathObject Real value is an integer (up to the tolerances given just above it), and is used by the subroutine stored in $integerCoefficients
.
The way it works is the following: the student's parsed answer ($ans->{student_formula}
) will be an equality (otherwise the answer checker will have produced an error message, and so $ans->{ans_message}
will not be empty), so we create a new formula by subtracting the right-hand side from the left-hand side. (This gives Ax+By-C from your origianl Ax + By = C.) From this, we compute the values of A, B, and C (or actually -C, but it doesn't really matter) and check if they are intergers. If not, an error message is reported and the score is set to 0. That's pretty much all there is to it.
Note that the message about integer coefficients will ALWAYS be given if the coefficients are not integers (and there is no other message). That's true whether the answer is otherwise correct or not. If you want the message to be issued only if the formula is otherwise correct but with non-integer coefficients, change $ans->{ans_message} eq ""
to $ans->{score} == 1
instead. That will perform the integer check only when the answer is correct.
Note that the integer check is a fuzzy check, meaning the coefficients must be integers up to the given tolerances. You may want to make them more restrictive.
Finally, note that this does not enforce a specific form for the student's answer, so all the examples I gave above are allowed (and many more).
You can, of course, package up the two subroutines into a macro file for use in multiple problems, though the Context()
call that sets the tolerances needs to be done after the Context("ImplicitPlane")
call or the values will be lost. You could put both into the macro file, but I'd argue against it (as it is not good for macro files to cause changes of that sort). Setting them both within the problem is probably better, and would let you use the same macro file for problems about actual planes, not just lines. It would also let the problem author determine the tolerances that are needed.
Hope that works for you.
Davide