How do I get WW to randomly choose from a list of variable names? I would like to have a list of variable names, something like, {x, t, m, y, q, ...} and randomly choose one of these variable names in a problem.
Mary
Hi Mary,
One way to do this would be to select a variable from an array using a randomly chosen index.
@var_array = ( 'w', 'x', 'y', 'z' );
$var_index = random(0,3,1);
$var = $var_array[$var_index];
The first line of code defines an array (i.e., ordered list) of four strings (since they're in quotes) to be the variable names. Next, we need to choose one of the elements of @var_array to be the variable name. Since array indices start at 0 in Perl, the second line of code above randomly chooses an integer from 0, 1, 2, 3. The third line of code chooses the scalar value from the array that has the index $var_index. Notice that we used
$var_array[$var_index]
and not
@var_array[$var_index]
to be assigned to the scalar $var. The reason for this choice is that $var_array[$var_index] is a scalar value, while @var_array[$var_index] is a (slice of) an array so it is an array and not a scalar. This is a rather fine point about data types, and sometimes you can make this mistake without any negative consequences, but it's best not to make the mistake at all. I like to think of it as follows: we want to pull a scalar value out of an array, so we use $var_array[] instead of @var_array[].
Next, we need to add the chosen variable to the context as a variable (where variable is used in the mathematics sense, not the computer programming sense) that takes real number values. The answer checkers need to know that it is a real-valued variable so that they know what to do with it.
Context("Numeric")->variables->are($var=>'Real');
Note that we used variables->are() instead of variables->add(). By default, the Numeric context always has the real valued variable x. This means that variables->add('w'=>'Real') would have two variables in the context (x and w) while variables->are('w'=>'Real') would have only one variable (w). This is important because students who enter an expression in x will get an error message
Variable 'x' is not defined in this context
when there is only one variable (w) in the context. It's also better to have the minimum number of variables to improve the reliability and accuracy of the answer checker.
Finally, we treat $var as we would any other variable in formulas. For example:
$answer = Compute("2*$var");
A complete minimal working example is given below.
Good luck and let us know if you have any more questions!
Paul Pearson
##################################################
DOCUMENT();
loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGcourse.pl",
);
TEXT(beginproblem());
$showPartialCorrectAnswers = 1;
@var_array = ( 'w', 'x', 'y', 'z' );
$var_index = random(0,3,1);
$var = $var_array[$var_index];
Context("Numeric")->variables->are($var=>'Real');
$answer = Compute("2*$var");
Context()->texStrings;
BEGIN_TEXT
Write an expression for two times \( $var \).
$BR
\{ ans_rule(20) \}
END_TEXT
Context()->normalStrings;
ANS( $answer->cmp() );
ENDDOCUMENT();
One way to do this would be to select a variable from an array using a randomly chosen index.
@var_array = ( 'w', 'x', 'y', 'z' );
$var_index = random(0,3,1);
$var = $var_array[$var_index];
The first line of code defines an array (i.e., ordered list) of four strings (since they're in quotes) to be the variable names. Next, we need to choose one of the elements of @var_array to be the variable name. Since array indices start at 0 in Perl, the second line of code above randomly chooses an integer from 0, 1, 2, 3. The third line of code chooses the scalar value from the array that has the index $var_index. Notice that we used
$var_array[$var_index]
and not
@var_array[$var_index]
to be assigned to the scalar $var. The reason for this choice is that $var_array[$var_index] is a scalar value, while @var_array[$var_index] is a (slice of) an array so it is an array and not a scalar. This is a rather fine point about data types, and sometimes you can make this mistake without any negative consequences, but it's best not to make the mistake at all. I like to think of it as follows: we want to pull a scalar value out of an array, so we use $var_array[] instead of @var_array[].
Next, we need to add the chosen variable to the context as a variable (where variable is used in the mathematics sense, not the computer programming sense) that takes real number values. The answer checkers need to know that it is a real-valued variable so that they know what to do with it.
Context("Numeric")->variables->are($var=>'Real');
Note that we used variables->are() instead of variables->add(). By default, the Numeric context always has the real valued variable x. This means that variables->add('w'=>'Real') would have two variables in the context (x and w) while variables->are('w'=>'Real') would have only one variable (w). This is important because students who enter an expression in x will get an error message
Variable 'x' is not defined in this context
when there is only one variable (w) in the context. It's also better to have the minimum number of variables to improve the reliability and accuracy of the answer checker.
Finally, we treat $var as we would any other variable in formulas. For example:
$answer = Compute("2*$var");
A complete minimal working example is given below.
Good luck and let us know if you have any more questions!
Paul Pearson
##################################################
DOCUMENT();
loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGcourse.pl",
);
TEXT(beginproblem());
$showPartialCorrectAnswers = 1;
@var_array = ( 'w', 'x', 'y', 'z' );
$var_index = random(0,3,1);
$var = $var_array[$var_index];
Context("Numeric")->variables->are($var=>'Real');
$answer = Compute("2*$var");
Context()->texStrings;
BEGIN_TEXT
Write an expression for two times \( $var \).
$BR
\{ ans_rule(20) \}
END_TEXT
Context()->normalStrings;
ANS( $answer->cmp() );
ENDDOCUMENT();
Thanks, Paul. I have my problem working as I would like it now, and I understand a little more about arrays and some of the structure.--Mary
There is a slightly easier way of selecting the variable name:
list_random
. This function returns one of its arguments chosen at random. So
$var = list_random('w','x','y','z');would select the variable name at random, and could replace your three-line version of doing this.
[Of course, you could have done your version in only one line as well,
$var = ('w','x','y','z')[random(0,3,1)];but
list_random
is slightly cleaner, as you don't have to worry about knowing the number of elements in the array.]