DOCUMENT(); loadMacros('PGstandard.pl', 'MathObjects.pl', 'PGML.pl', 'parserMultiAnswer.pl', 'PGcourse.pl'); @letters = ('A' .. 'Z'); Context()->strings->add(map { $_ => {} } @letters); $num_letters = 6; @my_letters = (map { splice(@letters, random(0, $#letters), 1) } 1 .. $num_letters); $my_letters_string = join '', @my_letters; @tmp = (0 .. $num_letters - 1); @derangement = @my_letters[ map { splice(@tmp, random(0, $#tmp, 1), 1) } @tmp ]; for my $i (0 .. $num_letters - 2) { if ($derangement[$i] eq $my_letters[$i]) { # swap with letter on the right $derangement[$i] = $derangement[ $i + 1 ]; $derangement[ $i + 1 ] = $my_letters[$i]; } } if ($derangement[-1] eq $my_letters[-1]) { $derangement[-1] = $derangement[0]; $derangement[0] = $my_letters[-1]; } $der_string = join '', @derangement; $multi_ans = MultiAnswer(@derangement)->with( singleResult => 1, separator => ' ', tex_separator => '\hbox{ }', checker => sub { my ($correct, $student) = @_; my $stu_der_string = join '', @$student; Value::Error('Repeated letters detected') if ($stu_der_string =~ /([a-zA-Z])~~1/); Value::Error('Invalid letters entered') if ($stu_der_string !~ /^[$der_string]*$/); for my $i (0 .. $num_letters - 1) { if ($my_letters[$i] eq $student->[$i]) { $multi_ans->setMessage($i + 1, "$student->[$i] in original spot"); return 0; } } return 1; } ); BEGIN_PGML All questions are about the following ordering of letters:[:quad :] [$my_letters_string] a. Give a derangement of the original ordering. Enter one letter in each of the blanks. [_]{$multi_ans} [_]{$multi_ans} [_]{$multi_ans} [_]{$multi_ans} [_]{$multi_ans} [_]{$multi_ans} END_PGML ENDDOCUMENT();