WeBWorK Problems

parserFunction in answers

parserFunction in answers

by Genevieve Toutain -
Number of replies: 3
Hi again, 

I am working on authoring some problems, and I am running into a snag.  I would like students to get some practice using function notation, so I would like the required answer to be something like "f(2)" without actually evaluating this to a number. 

I have successfully used parserFunction to evaluate a function easily through out a problem, ie:

DOCUMENT();        

loadMacros("parserFunction.pl",);

TEXT(beginproblem());

parserFunction(f => "2x");

BEGIN_TEXT

\( f(2) = \) \{ Compute( "f(2)" ) \}

END_TEXT 

ENDDOCUMENT();        


This prints f(2)=4 nicely, and I can figure out how to have the answer blank check again 4 the value of f(2), but I can't figure out how to have it check against "f(2)" the actual string.  As a work around, I have been using a string compare, but it seems like maybe there is a classier way to do this.  Especially when it comes to decimals-f(1/2) should be a correct answer to f(.5), but a string comparison will miss that. 


Any help would be greatly appreciated!


In reply to Genevieve Toutain

Re: parserFunction in answers

by Davide Cervone -
The usual approach is to use parserFunction to produce a function that is unlikely to be replicated accidentally by a student. For example:
  parserFunction(f => "sin(x) + ln(x^2+1)");
In this case, f(2) is not something the students would be likely to type on their own without the use of f().

When you do this, you will also want to set the formatStudentAnswers context flag so that the numeric answer isn't shown, but rather the reduced parsed answer (otherwise the student will see a funny decimal number as their answer rather than f(2)).

Here is an example:

loadMacros("parserFunction.pl");

Context("Numeric");
Context()->flags->set(formatStudentAnswer => "reduced");

parserFunction(f => "sin(x) + ln(x^2+1)");

$a = Compute("f(2)");

BEGIN_TEXT
\(f(2)\) = \{$a->ans_rule\}
END_TEXT
ANS($a->cmp);

Hope that does what you are looking for.

In reply to Davide Cervone

Re: parserFunction in answers

by Paul Pearson -
Hi all,

Davide, your answer was great.  I would like to ask a related follow up question.  Is it possible to use a custom answer checker that will set the student_value in the answer hash to be something else?  In the code below, I am able to set the student_value to something else (in this case, the preview_text_string); however, when I type the answer f(2) in the answer box and click submit answers, the "Entered" answer displays 8 instead of f(2) as I had hoped it would.  So, my general question is, "How can I change values in the answer hash and have those changes appear in the answer feedback given to students when they submit their answers?"

Thanks!

Paul Pearson



#####################

DOCUMENT();        

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"parserFunction.pl",
);

TEXT(beginproblem());

Context('Numeric');
parserFunction("f(x)" => "x^3");

$answer = Compute( "f(2)" );


BEGIN_TEXT

\( f(2) = \) \{ ans_rule(10) \}

END_TEXT 

ANS( $answer->cmp( checker=>sub {
    my ( $correct, $student, $ansHash ) = @_;

    warn $ansHash->{student_value}; # can comment this out
    $ansHash->{student_value} = $ansHash->{preview_text_string};
    warn $ansHash->{student_value}; # can comment this out

    return $correct == $student;
} ) );

ENDDOCUMENT();        
In reply to Paul Pearson

Re: parserFunction in answers

by Davide Cervone -
The student_value property is the wrong one to change. This is (and should always be) the MathObject that was obtained from parsing the student's answer. It is a mistake to replace this by a string, as other parts of WW may look at this value and expect to have a MathObject (e.g., AnswerHints, or other post-filters).


The field that ends up in the "Entered" column is student_ans (corresponding to corrections, just as student_value corresponds to correct_value). You certainly can set that during a custom answer checker.


But there is an easier way. The formatStudentAnswer flag in the Context controls how the entered field will be displayed. If you want it to be "f(2)" rather than "8", set it to parsed or reduced, as I did in my example above. The difference between the two is that reduced will reduce constant expressions, and so will make "f(2+3)" into "f(5)", while parsed will show the original without any modifications (so would show "f(2+3)").