I thought about switching to the unorderedAnswers.pl helper functions but I didn't know how to group the pairs of solutions togethers.
I've also included the code we've been using below.
Thank you!
Patrick Spencer
University of Missouri
DOCUMENT();
loadMacros(
"AnswerFormatHelp.pl",
"MathObjects.pl",
"PeriodicRerandomization.pl",
"PGgraphmacros.pl",
"PGstandard.pl",
"parserMultiAnswer.pl",
"parserPopUp.pl",
);
TEXT(beginproblem());
PeriodicRerandomization("3");
$refreshCachedImages = 1;
$showPartialCorrectAnswers = 1;
#################################################################
# setup contexts and variables
#################################################################
Context("Numeric");
Context()->strings->add("even"=>{}, "e"=>{alias=>"even"},
"odd"=>{}, "o"=>{alias=>"odd"},
"positive"=>{}, "pos"=>{alias=>"positive"}, "p"=>{alias=>"positive"},
"negative"=>{}, "neg"=>{alias=>"negative"}, "n"=>{alias=>"negative"});
Context()->{error}{msg}{"Operands of '*' can't be words"} = " ";
#Context()->{error}{msg}{"Can't convert an Empty Value to a Real Number"} = " ";
$numzeros = random(2,5);
do {</font></div><div><font face="courier new, courier, monospace"> # posszeros = possible zeros?</font></div><div><font face="courier new, courier, monospace"> @posszeros = (-10..10);</font></div><div><font face="courier new, courier, monospace"> # zeros = actual zeros?</font></div><div><font face="courier new, courier, monospace"> @zeros = (1..$numzeros);</font></div><div><font face="courier new, courier, monospace"> for ($i = 0; $i < $numzeros; $i++) {</font></div><div><font face="courier new, courier, monospace"> $zeros[$i] = list_random(@posszeros);</font></div><div><font face="courier new, courier, monospace"> if ($numzeros == 2 || $numzeros == 3) {</font></div><div><font face="courier new, courier, monospace"> $powers[$i] = random(2,3);</font></div><div><font face="courier new, courier, monospace"> } else {</font></div><div><font face="courier new, courier, monospace"> $powers[$i] = random(1,2);</font></div><div><font face="courier new, courier, monospace"> }
$removed = 0;
$count = 0;
do {</font></div><div><font face="courier new, courier, monospace"> if ($posszeros[$count] == $zeros[$i]) {</font></div><div><font face="courier new, courier, monospace"> $tmp = $posszeros[$count];</font></div><div><font face="courier new, courier, monospace"> $posszeros[$count] = $posszeros[scalar(@posszeros)-1];</font></div><div><font face="courier new, courier, monospace"> $posszeros[scalar(@posszeros)-1] = $tmp;</font></div><div><font face="courier new, courier, monospace"> pop(@posszeros);</font></div><div><font face="courier new, courier, monospace"> $removed = 1;</font></div><div><font face="courier new, courier, monospace"> }
$count++;
} until ($removed || $count == scalar(@posszeros));
$removed = 0;
$count = 0;
do {</font></div><div><font face="courier new, courier, monospace"> if ($posszeros[$count] == $zeros[$i]-1) {</font></div><div><font face="courier new, courier, monospace"> $tmp = $posszeros[$count];</font></div><div><font face="courier new, courier, monospace"> $posszeros[$count] = $posszeros[scalar(@posszeros)-1];</font></div><div><font face="courier new, courier, monospace"> $posszeros[scalar(@posszeros)-1] = $tmp;</font></div><div><font face="courier new, courier, monospace"> pop(@posszeros);</font></div><div><font face="courier new, courier, monospace"> $removed = 1;</font></div><div><font face="courier new, courier, monospace"> }
$count++;
} until ($removed || $count == scalar(@posszeros));
$removed = 0;
$count = 0;
do {</font></div><div><font face="courier new, courier, monospace"> if ($posszeros[$count] == $zeros[$i]+1) {</font></div><div><font face="courier new, courier, monospace"> $tmp = $posszeros[$count];</font></div><div><font face="courier new, courier, monospace"> $posszeros[$count] = $posszeros[scalar(@posszeros)-1];</font></div><div><font face="courier new, courier, monospace"> $posszeros[scalar(@posszeros)-1] = $tmp;</font></div><div><font face="courier new, courier, monospace"> pop(@posszeros);</font></div><div><font face="courier new, courier, monospace"> $removed = 1;</font></div><div><font face="courier new, courier, monospace"> }
$count++;
} until ($removed || $count == scalar(@posszeros));
}
$yint = 1;
for ($i = 0; $i < $numzeros; $i++) {</font></div><div><font face="courier new, courier, monospace"> $yint = $yint*((-$zeros[$i])**$powers[$i]);</font></div><div><font face="courier new, courier, monospace"> }
# this sub routine represents what is to be the graphed polynomial
sub poly {</font></div><div><font face="courier new, courier, monospace"> my $x = shift(); </font></div><div><font face="courier new, courier, monospace"> $prod = 1;</font></div><div><font face="courier new, courier, monospace"> for ($i = 0; $i < $numzeros; $i++) {</font></div><div><font face="courier new, courier, monospace"> $prod = $prod*(($x - $zeros[$i])**$powers[$i]);</font></div><div><font face="courier new, courier, monospace"> }
return $prod;
};
# sort zeros from low to high;
$swapped = 1;
$count = 0;
while ($swapped) {</font></div><div><font face="courier new, courier, monospace"> $swapped = 0;</font></div><div><font face="courier new, courier, monospace"> $count++;</font></div><div><font face="courier new, courier, monospace"> for ($i = 0; $i < $numzeros - $count; $i++) {</font></div><div><font face="courier new, courier, monospace"> if ($zeros[$i] > $zeros[$i+1]) {</font></div><div><font face="courier new, courier, monospace"> $tmp = $zeros[$i];</font></div><div><font face="courier new, courier, monospace"> $zeros[$i] = $zeros[$i+1];</font></div><div><font face="courier new, courier, monospace"> $zeros[$i+1] = $tmp;</font></div><div><font face="courier new, courier, monospace"> $swapped = 1;</font></div><div><font face="courier new, courier, monospace"> }
}
}
# this next bit is to be sure that the gap between the low or high point
# between zeros and the x-axis is not too small
for ($i = 0; $i < $numzeros-1; $i++) {</font></div><div><font face="courier new, courier, monospace"> $maxs[$i] = 0;</font></div><div><font face="courier new, courier, monospace"> }
for ($j = 0; $j < $numzeros-1; $j++) {</font></div><div><font face="courier new, courier, monospace"> $steps = 100;</font></div><div><font face="courier new, courier, monospace"> $stepsize = ($zeros[$j+1] - $zeros[$j])/$steps;</font></div><div><font face="courier new, courier, monospace"> for ($k = 0; $k < $steps; $k++) {</font></div><div><font face="courier new, courier, monospace"> $tmp = abs(poly($zeros[$j]+$k*$stepsize));</font></div><div><font face="courier new, courier, monospace"> if ($tmp > $maxs[$j]) {</font></div><div><font face="courier new, courier, monospace"> $maxs[$j] = $tmp; </font></div><div><font face="courier new, courier, monospace"> }
}
}
$min = min(@maxs);
$max = max(@maxs);
$scale = random(5,9);
$a = random(-1,1,2)*$scale/max($max);
$tmp1 = abs($min*$a);
$tmp2 = abs($max*$a);
} until (abs($tmp2/$tmp1) < 3*$scale/2);
$expn = sub {</font></div><div><font face="courier new, courier, monospace"> my $x = shift(); </font></div><div><font face="courier new, courier, monospace"> $prod = $a;</font></div><div><font face="courier new, courier, monospace"> for ($i = 0; $i < $numzeros; $i++) {</font></div><div><font face="courier new, courier, monospace"> $prod = $prod*(($x - $zeros[$i])**$powers[$i]);</font></div><div><font face="courier new, courier, monospace"> }
return $prod;
};
$minx = min($zeros[0],0)-3;
$miny = -10;
$maxx = max($zeros[$numzeros-1],0)+3;
$maxy = 10;
$gsize = 400;
$graph = init_graph($minx, $miny, $maxx, $maxy, size=>[$gsize,$gsize]);
for ($i = $minx; $i <= $maxx; $i++) {</font></div><div><font face="courier new, courier, monospace"> $graph->moveTo($i,$miny);</font></div><div><font face="courier new, courier, monospace"> $graph->lineTo($i,$maxy,'gray',1);</font></div><div><font face="courier new, courier, monospace">}
for ($i = $miny; $i <= $maxy; $i++) {</font></div><div><font face="courier new, courier, monospace"> $graph->moveTo($minx,$i);</font></div><div><font face="courier new, courier, monospace"> $graph->lineTo($maxx,$i,'gray',1);</font></div><div><font face="courier new, courier, monospace">}
$graph->moveTo($minx, 0);
$graph->arrowTo($maxx, 0, 'black', 2);
$graph->arrowTo($minx, 0, 'black', 2);
$graph->moveTo(0, $miny);
$graph->arrowTo(0, $maxy, 'black', 2);
$graph->arrowTo(0, $miny, 'black', 2);
$graph->lb(new Label($maxx-0.1, 0.4, 'x', 'black', 'bottom', 'right'));
$graph->lb(new Label(0.4, $maxy-0.1, 'y', 'black', 'top', 'left'));
for ($i = $minx+1; $i < $maxx; $i++) {</font></div><div><font face="courier new, courier, monospace"> if ($i != 0 && $i % 5 == 0 || $i == 1) {</font></div><div><font face="courier new, courier, monospace"> $graph->lb(new Label($i,-0.1,$i, 'black', 'top','center'));</font></div><div><font face="courier new, courier, monospace"> }
}
for ($i = $miny+1; $i < $maxy; $i++) {</font></div><div><font face="courier new, courier, monospace"> if ($i != 0 && $i % 5 == 0 || $i == 1) {</font></div><div><font face="courier new, courier, monospace"> $graph->lb(new Label(-0.1,$i,$i, 'black', 'middle', 'right'));</font></div><div><font face="courier new, courier, monospace"> }
}
for ($i = 0; $i < $numzeros; $i++) {</font></div><div><font face="courier new, courier, monospace"> $graph->stamps(closed_circle($zeros[$i],0,'blue'));</font></div><div><font face="courier new, courier, monospace">}
$fun = new Fun($expn, $graph);
$fun->steps(1500);
$fun->domain($minx,$maxx);
$zerosans = List(@zeros);
for ($i = 0; $i < $numzeros; $i++) {</font></div><div><font face="courier new, courier, monospace"> if ($powers[$i] % 2 == 0) {</font></div><div><font face="courier new, courier, monospace"> $mltpy[$i] = "even";</font></div><div><font face="courier new, courier, monospace"> } else {</font></div><div><font face="courier new, courier, monospace"> $mltpy[$i] = "odd";</font></div><div><font face="courier new, courier, monospace"> }
}
for ($i = 0; $i < $numzeros; $i++) {</font></div><div><font face="courier new, courier, monospace"> $answers[2*$i] = $zeros[$i];</font></div><div><font face="courier new, courier, monospace"> $answers[2*$i+1] = $mltpy[$i]</font></div><div><font face="courier new, courier, monospace">}
$ma = MultiAnswer(@answers)->with(
singleResult => 0,
allowBlankAnswers => 1,
checker => sub {</font></div><div><font face="courier new, courier, monospace"> $num = scalar(@answers);</font></div><div><font face="courier new, courier, monospace"> my ($correct, $student, $self) = @_;</font></div><div><font face="courier new, courier, monospace"> my @ac = @{$correct};
my @st = @{$student};
my @ans = (0..scalar(@ac)/2);
for ($i = 0; $i < $num; $i++) {</font></div><div><font face="courier new, courier, monospace"> $returnans[$i] = 0;</font></div><div><font face="courier new, courier, monospace"> }
for ($i = 0; $i < $num/2; $i++) {</font></div><div><font face="courier new, courier, monospace"> $hasbeenused[$i] = 0;</font></div><div><font face="courier new, courier, monospace"> }
for ($i = 0; $i < scalar(@ac)/2; $i++) {</font></div><div><font face="courier new, courier, monospace"> $ans[$i] = [$ac[2*$i],$ac[2*$i+1]];</font></div><div><font face="courier new, courier, monospace"> }
for ($i = 0; $i < scalar(@ac)/2; $i++) {</font></div><div><font face="courier new, courier, monospace"> for ($j = 0; $j < scalar(@ac)/2; $j++) {</font></div><div><font face="courier new, courier, monospace"> if ($ans[$i][0] == $st[2*$j] && $ans[$i][1] == $st[2*$j+1] && $hasbeenused[$i] != 1) {</font></div><div><font face="courier new, courier, monospace"> $returnans[0][2*$j] = 1;</font></div><div><font face="courier new, courier, monospace"> $returnans[0][2*$j+1] = 1;</font></div><div><font face="courier new, courier, monospace"> $hasbeenused[$i] = 1;</font></div><div><font face="courier new, courier, monospace"> }
}
}
for ($i = 0; $i < $num; $i++) {</font></div><div><font face="courier new, courier, monospace"> $reans[0][$i] = $returnans[0][$i]; </font></div><div><font face="courier new, courier, monospace"> }
return @reans;
}
);
$degree = $powers[0];
for ($i = 1; $i < $numzeros; $i++) {</font></div><div><font face="courier new, courier, monospace"> $degree = $degree + $powers[$i];</font></div><div><font face="courier new, courier, monospace">}
if ($degree % 2 == 0) {</font></div><div><font face="courier new, courier, monospace"> $degreeans = "even";</font></div><div><font face="courier new, courier, monospace">} else {</font></div><div><font face="courier new, courier, monospace"> $degreeans = "odd";</font></div><div><font face="courier new, courier, monospace">}
if ($a < 0) {</font></div><div><font face="courier new, courier, monospace"> $leadcoeffans = "negative";</font></div><div><font face="courier new, courier, monospace">} else {</font></div><div><font face="courier new, courier, monospace"> $leadcoeffans = "positive";</font></div><div><font face="courier new, courier, monospace">}
$dispzeros = "$zeros[0]";
$dispmults = "$mltpy[0]";
for ($i = 1; $i < $numzeros; $i++) {</font></div><div><font face="courier new, courier, monospace"> $dispzeros = ($dispzeros).", ".($zeros[$i]);</font></div><div><font face="courier new, courier, monospace"> $dispmults = ($dispmults).", ".($mltpy[$i]);</font></div><div><font face="courier new, courier, monospace">}
$degree = PopUp([" ","even", "odd"], "$degreeans");
$lead_coef_sgn = PopUp([" ","positive", "negative"], "$leadcoeffans");
#################################################################
# state the problem
#################################################################
Context()->texStrings;
BEGIN_TEXT
$PAR
$BCENTER
\{ image(insertGraph($graph), width=>$gsize, height=>$gsize, tex_size=>300 ); \}
$ECENTER
$PAR
Find the following information pertaining to the polynomial, \(f(x)\), graphed above.
$PAR
(a) The zeros of \(f(x)\) are \(x = \) \{ans_rule(15)\} (separate by commas) and
END_TEXT
for ($i = 0; $i < $numzeros; $i++) {</font></div><div><font face="courier new, courier, monospace"> if ($i == $numzeros-2) {</font></div><div><font face="courier new, courier, monospace"> BEGIN_TEXT</font></div><div><font face="courier new, courier, monospace"> $PAR</font></div><div><font face="courier new, courier, monospace"> $SPACE $SPACE $SPACE $SPACE the zero \(x = \) \{$ma->ans_rule(5)\} has \{$ma->ans_rule(5)\} multiplicity and,
$PAR
END_TEXT
} elsif ($i == $numzeros-1) {</font></div><div><font face="courier new, courier, monospace"> BEGIN_TEXT</font></div><div><font face="courier new, courier, monospace"> $PAR</font></div><div><font face="courier new, courier, monospace"> $SPACE $SPACE $SPACE $SPACE the zero \(x = \) \{$ma->ans_rule(5)\} has \{$ma->ans_rule(5)\} multiplicity.
$PAR
END_TEXT
} else {</font></div><div><font face="courier new, courier, monospace"> BEGIN_TEXT</font></div><div><font face="courier new, courier, monospace"> $PAR</font></div><div><font face="courier new, courier, monospace"> $SPACE $SPACE $SPACE $SPACE the zero \(x = \) \{$ma->ans_rule(5)\} has \{$ma->ans_rule(5)\} multiplicity,
$PAR
END_TEXT
}
}
BEGIN_TEXT
$PAR
(b) The degree of \(f(x)\) is \{$degree->menu()\}.
$PAR
(c) The leading coefficient of \(f(x)\) is \{$lead_coef_sgn->menu()\}.
END_TEXT
#################################################################
# check the answer
#################################################################
ANS(Compute($zerosans)->cmp());
ANS($ma->cmp());
ANS($degree->cmp());
ANS($lead_coef_sgn->cmp());
#################################################################
# use PeriodicRerandomization to write the answer and generate a new
# version of the problem
#################################################################
if ($attempts_modp == 0 && $actualAttempts != 0) {</font></div><div><font face="courier new, courier, monospace"> BEGIN_TEXT</font></div><div><font face="courier new, courier, monospace"> $PAR</font></div><div><font face="courier new, courier, monospace"> ${BBOLD}Answer:${EBOLD}
$PAR
(a) The zeros are \(x = $dispzeros\) with $dispmults multiplicity, respectively.
$PAR
(b) The degree is $degreeans.
$PAR
(c) The leading coefficient is $leadcoeffans.
$PAR
END_TEXT
} else {</font></div><div><font face="courier new, courier, monospace"> BEGIN_TEXT</font></div><div><font face="courier new, courier, monospace"> $PAR</font></div><div><font face="courier new, courier, monospace"> ${BBOLD}Help:${EBOLD} Type ${BBOLD}even${EBOLD} or ${BBOLD}odd${EBOLD} for multiplicities and the degree. Type ${BBOLD}pos${EBOLD} for positive or ${BBOLD}neg${EBOLD} for negative for the leading coefficient. You must have the corresponding multiplicity correct for each zero in order to receive credit!
$BR
END_TEXT
}
Context()->normalStrings;
PeriodicStatus();
ENDDOCUMENT();