exams num_to_schoice to include wrong alternatives

Viewed 49

I am using num_to_choice to generate 5 options for a numeric exercise using the r exams package.

I want my sc$questions to include the correct solution (res) plus two calculated wrong solutions (err1 and err2). I am using this code:

sc <- num_to_schoice(res, digits=3, wrong=c(err1, err2))

I do get the five options generated, one with the correct solution (res), but none of the other four options include err1 and err2. Reading the num_to_choice documentation I find:

"The wrong solutions can be provided or are generated randomly. If wrong is provided only up to 2 elements of it are used in order to assure some random solutions."

However, in my case none of the err1 or err2 options are included in the sc$questions. What am I missing here? How can I force the err options to be included in the sc$questions?

Here is an reproducible example:

v <- c(1225,4000,1372,974,956,940,1532,969,1070,685,220,407,903,239,283,368,483,352,77,699)
res <- sd(v)
err1 <- IQR(v)
err2 <- sqrt(var(v)*(length(v-1)/length(v)))
set.seed(1)
sc <- num_to_schoice(res, digits=3, wrong=c(err1, err2), range=c(0,max(v)))

and here is the solution generated by sc$questions:

The result is "specified 'wrong' is too small for 'delta'"

1 Answers

In your example

In your case err2 and res are identical:

identical(res, err2)
## [1] TRUE

That is why num_to_schoice() returns NULL along with a warning that should inform you that the difference from res to the wrong argument is too small for the given delta. Hence, it is not possible to include res as the correct solution and err2 as a wrong solution.

The source of the problem is that you compute

length(v - 1)

which is the same as length(v) rather than the intended

length(v) - 1

If you do

err2 <- sqrt(var(v) * (length(v) - 1)/length(v))

Then you get the desired

set.seed(1)
num_to_schoice(res, digits = 3, wrong = c(err1, err2))
## $solutions
## [1] FALSE FALSE FALSE  TRUE FALSE
## 
## $questions
## [1] "$819.235$"  "$634.000$"  "$996.905$"  "$840.517$"  "$1222.200$"

More generally

By design num_to_schoice() is rather conservative: If it thinks it cannot find a set of items with the desired properties it returns NULL rather than trying to find an approximate solution. This is to avoid randomly getting exercises that might be simpler than intended.

Another typical example is that the range is too small and/or the delta too large to produce a list of five answer options that conform with all arguments. For example, let's assume we have the following correct solution and two distractors:

res <- 1.234
err1 <- 2.345
err2 <- 3.456

Then, the command you posted above will not work:

num_to_schoice(res, digits = 3, wrong = c(err1, err2))
## NULL
## Warning message:
## In num_to_schoice(res, digits = 3, wrong = c(err1, err2)) :
##   specified 'range' is too small for 'delta'

The reason is that the default delta is 1 and the default range is c(0.5, 1.5) * res in this case. And this is not large enough to accomodate five answers with a minimum delta of 1.

But if you increase the range (or alternatively decrease the delta) you get:

set.seed(1)
num_to_schoice(res, digits = 3, wrong = c(err1, err2), range = c(0, 10))
## $solutions
## [1] FALSE FALSE FALSE  TRUE FALSE
## 
## $questions
## [1] "$3.456$" "$2.345$" "$4.496$" "$1.234$" "$9.195$"

where res ends up in position 4 while err1 and err2 are in positions 2 and 1, respectively.

Related