# Shiny apps with math exercises

Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

It is often very useful to practise mathematics by automatically generated exercises.
One approach is multiple choice quizzes (MCQ), but it turns out to be
fairly difficult to generate authentic wrong answers.
Instead, we want the user to input the answer and be able to parse the answer and check
whether this is the correct answer.
There are many fun challenges in this, e.g. to verify that 2 is equal to 1 + 1
(as text strings the two are different, but mathematically they are equal, at least to a convenient approximation in this case).

In this post I will demonstrate how to use R package Ryacas (computer algebra system, CAS) and the R package iomath under development (as well as shiny) to make a small, powerful Shiny app.
The resulting app is available at https://github.com/r-cas/shinymathexample.

First I will show the app, and then I will show a few central lines of code.

## The shinymathexample app

First, the shinymathexample app
presents the question: The answer can the be written and checked: It even works for mathematical/numerical equality, not just text/string equality: Finally wrong answers are caught, too: ## Exercise generation

The exercise generation code (boiled down) is something like this:

choices_x_coef <- c("a", "2*a", "3*a")
choices_x_pow <- 1:3

generate_f <- function() {
x_coef <- sample(choices_x_coef, 1)
x_pow <- sample(choices_x_pow, 1)
x_part <- paste0(x_coef, "*x^", x_pow)
eq <- ysym(x_part)
eq
}

problem_f_eq <- generate_f()

true_ans <- list(
x = deriv(problem_f_eq, "x")
)

output$problem <- renderUI({ problem <- paste0("Let $$f(x) = ", tex(problem_f_eq), ".$$", "Calculate the derivative with respect ", "to \$$x\$$ and enter the result below.") res <- withMathJax( helpText(problem) ) return(res) }) ## Validation The validation code (boiled down) is something like this: reply <- input$answer_x

if (inherits(parsed_input, "error")) {
stop("Could not prepare the input (remember that I'm simple-minded!).")
}

error = function(e) e)

stop("Could not understand the input (remember that I'm simple-minded!).")
}

compare_grid <- expand.grid(
x = seq(-10, 10, len = 6),
a = seq(-10, 10, len = 6)
)
answer = true_ans$x, compare_grid = compare_grid), error = function(e) e) if (inherits(is_correct, "error")) { stop(paste0("Error: ", is_correct$message))
}

is_correct # TRUE/FALSE

## Remarks

Take a look at the complete code at https://github.com/r-cas/shinymathexample.

The provided example should illustrate that it is fairly easy to make something
relatively sophisticated.

Beside the central aspect of Ryacas (e.g. for derivatives etc.), iomath has the important function compare_reply_answer that
compares reply to answer over the grid of values defined by compare_grid.
Thus, equality of expressions are measured as point-wise equality over a finite number of points (e.g. 100) for different values of variables including an allowed tolerance.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.