Why is the while loop necessary in the following code chunk? Taken from the dist3 exercise provided in the R/exams package.
sc <- NULL
while (is.null(sc)) {
p <- c(sample(1:3, 1), sample(1:5, 1))
q <- c(sample(4:5, 1), sample((1:5)[-p[2]], 1))
sol <- sqrt(sum((p - q)^2))
err <- c(sqrt(sum((p + q)^2)), sqrt(sum(abs(p - q))))
err <- err[abs(err - sol) > 0.1]
if (length(err) > 1) err <- sample(err, 1)
sc <- num_to_schoice(sol, wrong = err,
range = c(0.1, 10), delta = 0.3, digits = 3)
}
In general the function
num_to_schoice()
- that in this example is responsible for updating the variablesc
upon which the while loop conditions - is not guaranteed to return a list with$questions
texts and corresponding logical$solutions
. Instead, it may returnNULL
along with a warning when it cannot set up the questions/solutions with the properties specified (range, minimum distance, etc.). See below for some illustrations.Therefore, to guarantee that an exercise that relies on
num_to_schoice()
always yields a valid solution, the single-choice listsc
is first initialized withNULL
and then parameters are resampled andnum_to_schoice()
recalled untilsc
is notNULL
anymore (but a list with questions/solutions). (Remark: I use this setup routinely in my own exercises and often do not check whether any problems may actually occur. In this particular setup it seems that the problem with a NULL value can never occur.)For illustration, consider the following simple examples where the correct solution is 10, we want a
delta
of at least 1 between the correct and any false solution, and we use different ranges for the false solutions.First, let's use the range [1, 20] which always finds some set of false solutions.
In contrast, the interval [9, 11] is never large enough for four false solutions with a minimal distance of 1.
Finally, the interval [7, 13] may or may not be large enough. This depends on an initial step carried out in
num_to_schoice()
where the function first decides how many of the four false solutions should be on the left vs. on the right of the correct solution. This is built into the function to avoid systematically generating question lists where the correct solution is (one of) the smallest or (one of) the largest.More impossible setups can occur when
wrong
solutions are pre-specified that are too close to the correct solution and/or make the interval too small etc. See the examples in?num_to_schoice
for more illustrations.