-2

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?

wp78de
  • 18,207
  • 7
  • 43
  • 71
Nyssa73
  • 13
  • 2

1 Answers1

0

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

  • allow random filler words, punctuation, etc before and after the answers; basically, anything that is not an answer (?:(?!(?:\1|\2|\3)).)*
  • and define the answers (with \b word boundaries as needed) in an alternation group in a way that does not allow repetitions

i.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

wp78de
  • 18,207
  • 7
  • 43
  • 71
  • Thank you so much for your answer! I realize regex is not a language tool but right now it is the only option I have within Canvas other than (1)entering every literal permutation I can think of or (2)hand grading 160 papers. I will try your suggestion! – Nyssa73 Oct 28 '20 at 14:08
  • I tried your suggestion in the online regex tester I am using on the phrase "rain. bright sunlight. a dog's bark." and it failed to find a match. I am trying to figure out why it doesn't find a match, but my debugging has failed so far. I would be happy to use the DEFINE structure, but I'm not sure how it fits in with the rest of what you gave me. Some additional help would be great! – Nyssa73 Nov 01 '20 at 22:22
  • @Nyssa73 The `(?(DEFINE)(?'subroutine'regex))` group is only in Perl and PCRE available but not in Ruby; the online demo's I provided are working, which one's do you refer to? – wp78de Nov 01 '20 at 22:51
  • Too bad about the DEFINE. I am using regex101.com. I copied the pattern you posted (^...$), removed all of the comments, and put it in the regular expression window in the tester. I then put the string "rain. bright sunlight. a dog's bark." in the Test String window. The result is "no match". Am I being stupid? – Nyssa73 Nov 01 '20 at 22:59
  • Argh! I just saw your link to the Ruby Demo! I'll play around with that tester. It must have failed because regex101.com is a PCRE tester? – Nyssa73 Nov 01 '20 at 23:02
  • @Nyssa73 no, but you need to use some extra regex flags specifically `x` and `i`; I should have pointed this out. Click on the PCRE Demo link above to see it in action; if your Quiz portlet does not allow to specify extra flags we can define them inline, prefixing the regex pattern with `(?x)(?i)` – wp78de Nov 01 '20 at 23:04
  • regex101 has different regex flavors, select them on the left; unfortunately, Ruby-regex is not among them; in fact, the Ruby flavor is very close to Perl but there are still some differences. – wp78de Nov 01 '20 at 23:07
  • Got it working! Thanks again!! – Nyssa73 Nov 02 '20 at 01:42