I work with Canvas in a middle school and am constructing quizzes which contain a question type called "fill-in-the-blank". A grading option for this type of question is to compare what the student typed in to a regex. The Quiz settings only allow me to enter a single regex and if the input matches the question is counted as correct. This is simple to do for single or few word answers. But I would like to ask something like, "list three different examples of environmental stimuli, ended with a period". So a correct input string might be the following:
rain. bright sunlight. a dog's bark.
but an incorrect input string would be:
water. water. a bicycle.
I can match individual phrases and split them using ([\w\s']*[^\.]?)
. This yields three matches in a regex tester. But I need to go further.
I need to check each phrase for a keyword, and then check if that keyword has been used before. Essentially, I need to match an alternation group without repetitions using a single regex pattern. Can this be done?
If I understood correctly, you want to have an alternation group without repetitions. This is a bit complex and has some limitations but can be done.
We need to
(?:(?!(?:\1|\2|\3)).)*
\b
word boundaries as needed) in an alternation group in a way that does not allow repetitionsi.e. a pattern like this using the regex flags gxi (or inlining (some of) them (?x)(?i)
^ # begin of string
(?:(?!(?:\1|\2|\3)).)*? # ungreedy anything that is not captured by group 1,2,or 3
( # 1th capturing group
(?:\brain\b|\bsunlight\b|\bbark) # Alternation group (answers) \b word-boundaries as needed
)
(?:(?!(?:\1|\2|\3)).)*? # ungreedy anything that is not captured by group 1,2,or 3
( # 3th capturing group
(?:(?!(?:\1|\3))(?:\brain\b|\bsunlight\b|\bbark)) # Answers not captured in group 1 or 3
)
(?:(?!(?:\1|\2|\3)).)*? # ungreedy anything that is not captured by group 1,2,or 3
( # 4th capturing group
(?:(?!(?:\2|\3))(?:\brain\b|\bsunlight\b|\bbark)) # Answers not captured by group 2 or 3
)
(?:(?!(?:\1|\2|\3)).)* # anything that is not captured by group 1,2,or 3
$ # end of string
The pattern could be simplified but I tried to keep the pattern readable (Though, techniques like (?(DEFINE).(?"answers"))
could help us to make the regex more maintainable.)
Ruby Rublar Demo (g
|global, and m
|multiline flags are default on tubular),
PCRE Demo (using gmxi
-flags)
Quizzes are using Ruby regular expressions which are very similar to PCRE but not exactly the same.
This shows the basic idea and should get you started. Nonetheless, a regex is not a linguistics tool nor an AI. The pattern is context-free and does not verify if the answers make actual sense, e.g. if we define rain|sunlight|bark
as possible answers this is valid:
Barking elephant, green Sunlight, purple rain, and other non-sense