From: Davide P. C. <dp...@un...> - 2005-12-31 17:00:55
|
> In a calculus problem, I want students to find critical points and > indicate if they correspond to maxima, minima, or neither. And I > don't want to give away in advance how many points there are. So I > was trying to coerce interval_cmp to do this for me by having it > evaluate a set of "intervals," viz., > interval_cmp( "(-2,min),(3,max)", 'unions'=>'no', > 'strings'=>['none','min','max','neither'] ); I'm not sure why you are using interval_cmp for this when you could use the List object directly. E.g., Context("Numeric")->strings->add(none=>{},min=>{},max=>{},neither=>{}); ANS(List("(-2,min),(3,max)")->cmp); There's really no need to mislabel this as an interval check when it isn't. You are really checking for a list of lists, which is just what List() is designed for. (I agree with John that the semantics of the traditional answer checkers are more direct, but the Parser versions do allow more flexibility, when it is needed.) > This works very well, until there is no maximum (or no minimum), in > which case > interval_cmp( "(-2,min)", 'unions'=>'no', > 'strings'=>['none','min','max','neither'] ); > has trouble: as student entering (-2,min) has her/his answer marked > wrong with the message "The parentheses for your list should be > removed." I was not able to reproduce this. Are you using current versions of all the Parser files? (In particular lib/Value/AnswerChecker.pm) In any case, there was a problem dealing with this that I have fixed, so you should get the AnswerChecker.pm that I have just added to teh CVS archive. The issue is that when a student types a list like "(1,max)" it is not clear if they mean the list containing two items, 1 and "max", or the list containing one item, the list "1,max". The default had been the former, which is probably a bad choice, since that turns out to be rarely what is intended. I have changed the answer checker to use the latter, and added a flag to allow the former behavior in those cases where it is desired. This should not adversely effect existing usages, as it only happens when the student explicitly includes the parens. Anyway, that should clear up your problem whether you use interval_cmp or the List object directly. > 1. Have I overlooked a better way of checking this type of problem? I think using List() directly makes more sense. > 2. Is there some feature of interval_cmp that I can change to get > a more > intuitive (at least from the perspective of a student) behavior? I think my change to the list checker will take care of this. > 3. Is there an easy tweak to interval_cmp that will have the same > effect? No need at this point. > I also have a problem where I want to check the answer "(0,min), > (a,max)", where a is a constant. My rather coarse solution was to > copy the interval_cmp evaluator into the problem, calling it > my_interval_cmp, and add the variable 'a' to the Parser Context. > Is there a better way of doing this? There wasn't a way using interval_cmp, so I added new "var" and "vars" flags that allow you to do interval_cmp("(0,min),(a,max)",var=>'a'); One of the problems with using this approach is that the warning messages will now say that you are looking for a formula rather than a constant. but in your case, since the items in your list are themselves lists, you should not get any type mismatch errors (since lists can be practically anything). The Parser doesn't know what the legitimate values for your list are, so can't issue warnings when the student types something different. If you want to provide more meaningful error messages, you can supply your own type checker as follows: Context("Numeric")->strings->are(none=>{},max=>{},min=>{},neither=>{}); Context()->variables->add(a=>'Real'); ANS(List("(0,max),(a,max)")->cmp( typeMatch => sub { my $student = shift; return 0 unless $student->type eq 'List' && $student->length == 2; my ($x,$t) = $student->value; return ($x->type eq 'Number' && $x->class ne 'Formula') && $t- >type eq 'String'; }, entry_type=>"a critical-point specification", )); $showPartialCorrectAnswers = 1; This overrides the type checker and supplies your own that checks that the student answer is a list of the desired form (a number followed by a string value). The list checker will call this on each answer, and will report an error if the result is zero (or false). I also supply an entry_type string that will be part of the messages. You will get messages like "Your first critical-point specification is incorrect" and "Your first value doesn't look like a critical- point specification (it looks like a ...)" in the situations where these apply. A more complicated approach would be to define your own Parser syntax, say "-2 = max" or "-2 => max" or some such, and then ask for a list of those. The "=" or "=>" would be an operator, and it could return a list formed by its two operands, so that the equality checking would as expected. It wouldn't be too hard to do, so if you want that, let me know and I'll give it a shot (I'm not doing it now, since I already spent most of the morning on this, and I have to get back to work :-). John's suggestion of an array of text entries with pop-up lists also looks like a possibility, though you would have to handle the pairing of numbers with menus yourself, and allowing the points in any order (and not repeated) and so on. The Multipart object can certainly handle that, though there is some work to do. I haven't tried nested multi-parts, but if that worked, it would simplify things considerably (use a bunch of ordered multi-parts for the pairs of number with pop-up, and then collect those into an unordered multipart). Davide |