WeBWorK Problems

Precalculus Answer Format - List of ordered pairs

Precalculus Answer Format - List of ordered pairs

by Nathan Wodarz -
Number of replies: 2
I'd like to give a problem with an answer a list of ordered pairs. In particular, students would be given an equation, and asked to come up with 3 distinct ordered pairs satisfying the equation. However, I haven't been able to figure out a decent method of checking that, and I'm not sure I understand answer evaluators well enough to write one on my own.

In reply to Nathan Wodarz

Re: Precalculus Answer Format - List of ordered pairs

by Davide Cervone -
Well, you are in luck, because all the pieces are there to make it possible to do what you want. There are several approaches, but I am going to suggest that you use the MultiAnswer object and the SolutionFor objects, together with the default MathObjects Points. I've attached a PG file that implements my suggestions; here's how it works.

The SolutionFor object allows you to define an equality (in whatever variables are defined in your problem), and get an answer checker that determines if a point satisfies the equation. We won't be using its answer checker directly, but it also overloads the == operator to test if a given point satisfies the equation, and we will use that to let use check several points.

The MultiAnswer object allows you to make a checker that has access to the answers supplied in more than one answer blank, and to use all of them to determine whether they are correct or not. We will use this to allow us to compare the answers to make sure they are distinct, in addition to being correct.

You begin by loading the parserMultiAnswer.pl and parserSolutionFor.pl libraries (together with MathObjects.pl). These are in the pg/macros directory, and you can view the comments in them for more details on how they work.



Then you set the context to the "Point" context so you have more than one variable defined and can produce points in your answers. Then you create the points that satisfy your equation and form a SolutionFor object with one of them (it is not used, but is required by the object).


    $p1 = Compute("(1,0)");
    $p2 = Compute("(2,sqrt(3))");
    $p3 = Compute("(-1,0)");

    $f = SolutionFor("x^2 - y^2 = 1",$p1);
Next you define the MultiAnswer object with three example points for the student (these will be shown as the correct answers if the student requests them after the due date). As part of this, you supply a checker routine that determines if the student's answers are correct. All of the type-checking and other bookkeeping functions are performed by the MultiAnswer object (and the underlying MathObjects), so you only need to provide the specific conditions under which the answers will be correct. This is the heart of the example.

    $ma = MultiAnswer($p1,$p2,$p3)->with(
      checker => sub {
        my ($correct,$student,$self,$ans) = @_;
        my @scores = (); my $isPreview = $main::inputs_ref->{previewAnswers};
        foreach my $i (1..scalar(@$student)) {
          my $score = ($f == $student->[$i-1]);  # SolutionFor makes this return 0 or 1
          foreach my $j (1..$i-1) {
            if ($student->[$i-1] == $student->[$j-1]) {
              $self->setMessage($i,"This is the same as your ".$self->NameForNumber($j)." point")
                unless $isPreview;
              $score = 0; last;
        return @scores;
The checker receives four parameters: a pointer to the array of correct answers (we ignore this), a pointer to the array of student answers, a pointer to the MultiAnswer object itself, and a pointer to the answer hash (which we also ignore). The checker is supposed to return either a single number (all parts will receive the same score) or an array of scores, one for each answer. We will do the latter so that partial credit can be awarded. We also determine if the Preview button was pushed so that we don't produce error messages that would give away part of the answer in that case.

The main portion of this checker is a loop that runs from 1 to the number of entries in the student array (it will be three in this problem, but that could change). For each student answer, we compute the score based on whether the student's point satisfies the equation ($f == $student->[$i] does this, because the SolutionFor object, $f, overloads the equality check to return 1 or 0 depending on whether the point satisfies the equation or not).

Next, we look through the previous answers and check if any are equal to this new one; if so, we report an error and mark this point incorrect. Then we add the score to the array and end the loop. Finally, we return the array of scores.

The remainder of the problem is just producing the text and installing the MultiAnswer's answer checker. The only other thing to note is that the answer rules must be produced by the MultiAnswer object, not by direct calls to ans_rule. This is the key to allowing the MultiAnswer access to all the answer blanks. Also note that the SolutionFor's Formula object is stored in a field named f so we can use that to display the equation the students are to solve.

      Consider the implicit equation
      Three distinct solutions to this equality are:
      \((x_1,y_1)\) = \{$ma->ans_rule(20)\}$BR
      \((x_2,y_2)\) = \{$ma->ans_rule(20)\}$BR
      \((x_3,y_3)\) = \{$ma->ans_rule(20)\}

    $showPartialCorrectAnswers = 1;

That's it. Hope that works for you.


PS, it would be possible to use the List object with a custom list checker to do this, but since you know there must be three answers, it's not really necessary to do a list, and the answer messages and partial credit will work better with three separate blanks, as the students will see more readily which answers are right and which aren't That is harder (though still possible) with the list checker, but that is for another message.

PPS, the attachment has unix-style line breaks, so if you try to view it on a PC, it might not format correctly. Best to move it directly to your WeBWorK server and view it there.