

1  =head1 NAME 
1  
2  


3  answerComposition.pl  An answer checker that determines if two functions 


4  compose to form a given function. 
2  
5  
3  =head1 DESCRIPTION 
6  =head1 DESCRIPTION 
4  
7  
5  ###################################################################### 
8  answerComposition.pl provides an answer checker that determines if two functions 
6  # 


7  # An answer checker that determines if two functions compose 


8  # to form a given function. (For use in problems where you ask 
9  compose to form a given function. This can be used in problems where you ask a 
9  # a student to break a given function into a composition of two 
10  student to break a given function into a composition of two simpler functions, 
10  # simpler functions, neither of which is allowed to be the identity 
11  neither of which is allowed to be the identity function. 
11  # function.) 


12  # 


13  
12  
14  =cut 
13  =cut 
15  
14  
16  sub _answerComposition_init {}; # don't reload this file 
15  sub _answerComposition_init {}; # don't reload this file 
17  
16  
18  =head3 COMPOSITION_ANS($fn_f,$fn_g) 
17  =head1 MACROS 
19  
18  
20  ###################################################################### 
19  =head2 COMPOSITION_ANS 
21  # 
20  


21  COMPOSITION_ANS($f, $g, %options) 


22  
22  # An answer checked to see if f composed with g matches a given function. 
23  An answer checked to see if $f composed with $g matches a given function,where 
23  # 


24  # Usage: COMPOSITION_ANS(f,g,options) 


25  # 


26  # where f and g are one possible decomposition of the target function 
24  $f and $g are one possible decomposition of the target function, and options are 


25  any of the options allowed by composition_ans_list() below. 


26  
27  # (these are used to display the "correct" answer, and the composition 
27  $f and $g are used to display the "correct" answer, and the composition is 
28  # is computed from them) and options are any of the options allowed 
28  computed from them. 
29  # by composition_ans_list() below. 
29  
30  # 


31  # This function actually supplies TWO answer checkers, for the two 
30  This function actually supplies TWO answer checkers, for the two previous answer 
32  # previous answer blanks. So be sure to call it immediately after 
31  blanks. So be sure to call it immediately after the answer blanks have been 
33  # the answer blanks have been supplied. (It may be best to use the 
32  supplied. (It may be best to use the NAMED_COMPOSITION_ANS checker below, which 
34  # NAMED_COMPOSITION_ANS checker below, which specifies the answer 
33  specifies the answer blanks explicitly.) 
35  # blanks explicitly.) 
34  
36  # 


37  # Example: 
35  Example: 
38  # 
36  
39  # BEGIN_TEXT 
37  BEGIN_TEXT 
40  # \(f\circ g = (1+x)^2\) when 
38  \(f\circ g = (1+x)^2\) when 
41  # \(f(x)\) = \{ans_rule(20)\} and \(g(x)\) = \{ans_rule(20)\} 
39  \(f(x)\) = \{ans_rule(20)\} and \(g(x)\) = \{ans_rule(20)\} 
42  # END_TEXT 
40  END_TEXT 
43  # COMPOSITION_ANS("x^2","1+x"); 
41  COMPOSITION_ANS("x^2","1+x"); 
44  # 


45  
42  
46  =cut 
43  =cut 
47  
44  
48  sub COMPOSITION_ANS { 
45  sub COMPOSITION_ANS { 
49  my $f = shift; my $g = shift; 
46  my $f = shift; my $g = shift; 
…  
…  
51  my $gID = ANS_NUM_TO_NAME($main::ans_rule_count); 
48  my $gID = ANS_NUM_TO_NAME($main::ans_rule_count); 
52  my %ans = composition_ans_list($fID=>$f,$gID=>$g,@_); 
49  my %ans = composition_ans_list($fID=>$f,$gID=>$g,@_); 
53  ANS($ans{$fID},$ans{$gID}); 
50  ANS($ans{$fID},$ans{$gID}); 
54  } 
51  } 
55  
52  


53  =head2 NAMED_COMPOSITION_ANS 


54  
56  =head3 NAMED_COMPOSITION_ANS(fID=>f,gID=>g,options) 
55  NAMED_COMPOSITION_ANS($fID=>$f, $gID=>$g, %options) 
57  
56  
58  ###################################################################### 


59  # 


60  # An answer checked to see if f composed with g matches a given function. 
57  An answer checked to see if $f composed with $g matches a given function, where 
61  # 


62  # Usage: NAMED_COMPOSITION_ANS(fID=>f,gID=>g,options) 


63  # 


64  # where fID and gID are the names of the answer rules for the functions 
58  $fID and $gID are the names of the answer rules for the functions $f and $g, and 
65  # f and g, and f and g are the answers for the functions. Options are 
59  $f and $g are the answers for the functions. %options are any of the options 
66  # any of the options allowed by composition_ans_list() below. 
60  allowed by composition_ans_list() below. 
67  # 
61  
68  # This routine allows you to put the f and g answer blanks at any 
62  This routine allows you to put the answer blanks for $f and $g at any location 
69  # location in the problem, and in any order. 
63  in the problem, and in any order. 
70  # 
64  
71  # Example: 
65  Example: 
72  # 
66  
73  # BEGIN_TEXT 
67  BEGIN_TEXT 
74  # \(g\circ f = (1+x)^2\) when 
68  \(g\circ f = (1+x)^2\) when 
75  # \(f(x)\) = \{NAMED_ANS('f',20)\} and \(g(x)\) = \{NAMED_ANS('g',20)\} 
69  \(f(x)\) = \{NAMED_ANS('f',20)\} and \(g(x)\) = \{NAMED_ANS('g',20)\} 
76  # END_TEXT 
70  END_TEXT 
77  # NAMED_COMPOSITION_ANS(f => "x^2", g => "1+x"); 
71  NAMED_COMPOSITION_ANS(f => "x^2", g => "1+x"); 
78  # 


79  
72  
80  =cut 
73  =cut 
81  
74  
82  sub NAMED_COMPOSITION_ANS {NAMED_ANS(composition_ans_list(@_))} 
75  sub NAMED_COMPOSITION_ANS {NAMED_ANS(composition_ans_list(@_))} 
83  
76  


77  =head2 composition_ans_list 


78  
84  =head3 composition_ans_list(fID=>f,gID=>g,options) 
79  composition_ans_list($fID=>$f, $gID=>$g, %options) 
85  
80  
86  ###################################################################### 


87  # 


88  # This is an internal routine that returns the named answer checkers 
81  This is an internal routine that returns the named answer checkers 
89  # used by COMPOSITION_ANS and NAMED_COMPOSITION_ANS above. 
82  used by COMPOSITION_ANS and NAMED_COMPOSITION_ANS above. 
90  # 
83  
91  # Usage: composition_ans_list(fID=>f,gID=>g,options) 


92  # 


93  # where fID and gID are the names of the answer rules for the functions 
84  $fID and $gID are the names of the answer rules for the functions and $f and $g 
94  # and f and g are the answers for these functions. Options are from 
85  are the answers for these functions. %options are from among: 
95  # among: 
86  
96  # 
87  =over 
97  # var => 'x' the name of the variable to use when 
88  
98  # both functions use the same one 
89  =item S<C<< var => 'x' >>> 
99  # 
90  
100  # vars => ['x','t'] the names of the variables for f and g 
91  the name of the variable to use when 
101  # 
92  both functions use the same one 
102  # showVariableHints => 1 or 0 
93  
103  # do/don't show errors when the variable 
94  =item S<C<< vars => ['x','t'] >>> 
104  # used by the student is incorrect 
95  
105  # 
96  the names of the variables for $f and $g 


97  


98  =item S<C<< showVariableHints => 1 or 0 >>> 


99  


100  do/don't show errors when the variable 


101  used by the student is incorrect 


102  


103  =back 
106  
104  
107  =cut 
105  =cut 
108  
106  
109  sub composition_ans_list { 
107  sub composition_ans_list { 
110  my ($fID,$f,$gID,$g,%params) = @_; my @IDs = ($fID,$gID); 
108  my ($fID,$f,$gID,$g,%params) = @_; my @IDs = ($fID,$gID); 
…  
…  
195  } 
193  } 
196  
194  
197  return (%ans); 
195  return (%ans); 
198  } 
196  } 
199  
197  
200  ###################################################################### 
198  =head2 message_cmp 
201  # 
199  


200  message_cmp($correct) 


201  
202  # Evaluator that always returns incorrect, with a given error 
202  Returns an answer evaluator that always returns incorrect, with a given error 
203  # message. Used by COMPOSITION_ANS to produce "dummy" answer 
203  message. Used by COMPOSITION_ANS to produce "dummy" answer checkers for the two 
204  # checkers for the two parts of the composition. 
204  parts of the composition. 
205  # 
205  


206  =cut 


207  
206  sub message_cmp { 
208  sub message_cmp { 
207  my $correct = shift; 
209  my $correct = shift; 
208  my $answerEvaluator = new AnswerEvaluator; 
210  my $answerEvaluator = new AnswerEvaluator; 
209  $answerEvaluator>ans_hash( 
211  $answerEvaluator>ans_hash( 
210  type => "message", 
212  type => "message", 
…  
…  
214  $answerEvaluator>install_evaluator(sub {shift}); 
216  $answerEvaluator>install_evaluator(sub {shift}); 
215  return $answerEvaluator; 
217  return $answerEvaluator; 
216  } 
218  } 
217  
219  
218  1; 
220  1; 


221  