PREP 2014 Question Authoring - Archived

Does \{$a->ans_rule()\} associate $a with the answer blank?

Does \{$a->ans_rule()\} associate $a with the answer blank?

by Fred Brulois -
Number of replies: 4
It would seem that the answer is no, based on the example below.
The correct answers are 
2 in the 1st blank
1 in the 2nd blank
and not 
1 in the 1st blank
2 in the 2nd blank
as one might expect.

DOCUMENT();
loadMacros(
  "PGstandard.pl",
  "MathObjects.pl"
);
TEXT(beginproblem());

######################################
#  Setup

Context("Numeric");

$one = Compute("1");
$two = Compute("2");

######################################
#  Main text

Context()->texStrings;
BEGIN_TEXT
 \{$one->ans_rule()\}
$PAR
\{$two->ans_rule()\}
END_TEXT
Context()->normalStrings;

######################################
#  Answers

ANS($two->cmp);
ANS($one->cmp);
$showPartialCorrectAnswers = 1;

ENDDOCUMENT();

In reply to Fred Brulois

Re: Does \{$a->ans_rule()\} associate $a with the answer blank?

by Paul Pearson -
Hi Fred,

In \{ $a->ans_rule \}, if you think of ->ans_rule() as a method (or function) being called on an object $a, it is returning the answer blank(s) associated to the object.  Some MathObjects will produce one answer blank, while others may need to produce several answer blanks.  For instance, if $a is a 2 by 3 matrix, then $a->ans_array should return six answer blanks in a 2 by 3 array in the html output.

I think you may be expecting $a->ans_rule to do three things: (1) produce answer blanks in the html output and (2) compare the answer the student enters in that answer blank to the correct answer, and (3) record the score in webwork's gradebook.  In fact, $a->ans_rule only does (1), not (2) or (3).  

For step (1), the answer blanks that are produced for the html form element are given names in the html source code such as AnSwEr0001, AnSwEr0002,... in the order in which they are generated from the PG source code.  For step (2), the student answers are collected from the html form in order and compared to the correct answers in the same order as they appear as arguments to ANS() or multiple ANS()'s.  For step (3), ANS() records the student's score in the gradebook (the webwork database).

So, in short, you should do things in the same order.  If you generate answer blanks via \{ $ans1->ans_rule \} and \{ $ans2->ans_rule \}, then you should score them in the same order using ANS($ans1->cmp); and ANS($ans2->cmp);.

Best regards,

Paul Pearson
In reply to Fred Brulois

Re: Does \{$a->ans_rule()\} associate $a with the answer blank?

by Davide Cervone -
Paul has already given you some good information about how the answer blanks are linked to the answers, but I wanted to reiterate that, in general, the association is given by the order: the first answer blank goes with the first ANS() call, the second blank with the second ANS() call, and so on.

Paul points out one of the important exceptions, things like Matrices that may produce more than one answer blank.

It is also possible to have what are called "named answer blanks" that associates an ID with a blank, and a "named answer checker" that uses that ID to find the answer rule that goes with it, but the use of these is rare.

Finally, we will hear on Monday about another mechanism for laying out the text of the problem that combines the text and answer sections into one piece, making a cleaner connection between the blanks and the answers that go with them.
In reply to Davide Cervone

Re: Does \{$a->ans_rule()\} associate $a with the answer blank?

by Joel Trussell -
I have run across the set all variables, not just the ones in the formula. I just forgot about that rule. I guess you have to use it more often than I do. So, I've removed x since I don't use it, and I inserted the comment about setting all the variables. 
The various pointers, hashes, etc. are still a bit of blur in my mind. 
$X ->{test_points} = [[0,0],[$N-1,$N-1]]; 
seems to be a reference to an array of references. How do I set an array to include the test points from 0 to N-1
# generate test points
for ($m=0; $m<$N; $m++) {
    $a[$m] = [$m,$m]; 
}
seems to be a start, but I'm not sure how to put that in 
$X ->{test_points} = [$a]; ????

In reply to Joel Trussell

Re: Does \{$a->ans_rule()\} associate $a with the answer blank?

by Davide Cervone -
Your $a[$m] = [$m,$m] uses the array @a, so you still have to make that into an array reference. You are almost there, but you want
    $X->{test_points} = [@a];
using @ not $a. The difference is that @a and $a is a scalar (and generally are two different variables, even though they have the same letter).

So why is $a[$m] rather than @a[$m]? Because the entry in the array is a scalar, so you need to use a dollar sign, indicating a scalar value, rather than an at sign (which would indicate an array).

Another reason is that you get a slice of an array using the @ form: @a[1,3,5] would be a new array made from the first, third, and fifth element of @a. So technically @a[$m] should be an array with one element, but because many people get this wrong (and I think it used to be the correct way to do it in very early versions of Perl), Perl handles @a[$m] as a scalar anyway.

Alternatively, you could use

    $P = [];
    for ($m=0; $m < $N; $m++) {
      $P->[$m] = [$m,$m]; 
    }
    $X->{test_points} = $P;
to make $P a reference to an array, and $P->[$m] to access the entries in the array.

Another approach would be to assign to the test points directly:

    $X->{tet_points} = [];
    for ($m=0; $m < $N; $m++) {
      $X->{test_points}[$m] = [$m,$m]; 
    }
Here, you could also do $X->{test_points}->[$m], but once you de-reference the first time (using ->), Perl assumes the remaining de-references when you use braces or brackets.

Finally, a very compact form:

    $X->{test_points} = [map { [$_,$_] } (0..$N-1)];
This uses the array of integers from 0 to $N-1 and maps them through code that returns an array reference with two elements, both equal to the integer from the original array. The resulting array of references is put into [...] so produce a reference to the array.