In order to create the rulebook, we need a dictionary of keywords, consisting of a priority number and a list of possible patterns, and responses to be made if the patterns do match. In code it looks something like this:
{"keyword":(priority,
[
[pattern,
response,
response],
[pattern,
response]
]),
"keyword":(priority,
[
[pattern,
response,
response]
])}
The pattern is a list that contain a list of words to search for and the number of words matching before and after it. The number 0 will mean zero or more words are found. For example, given a pattern like this:
[0,"I","am",0]
It will create match with phrases like, “maybe I am tired”, or “I am tired today” or simply “I am tired”
The response is a similar list except the textual pieces are not single words, and the number represents the word(s) in the pattern to substitute into the response.
So, given the pattern shown above, and if the user inputs this text:
“maybe I am tired today”
This will result in “maybe” as number 1, “I” as number 2, “am” as number 3, and “tired today” as number 4.
If we write a response as such:
["Is it because you are", 4, "that you came to see me?"]
The resulting exchange would be this:
?Maybe I am tired today
Is it because you are tired today that you came to see me?
Sometimes we will have no pattern matches. In that case we will come up with a generic response like, “please tell me more” or “that is very interesting”
Enforcing the rules
We need to create a matchPattern() function to match the user input to one of the patterns. First, we have to deal with wild cards, when the pattern is 0. If 0 is found to be the last item on the pattern list, then we simply append the rest of the text. Otherwise we will create another function called matchWildCard() to handle it. Write this above the main program:
def matchPattern(pattern, text):
matches = []
for i in range(len(pattern)):
if pattern[i] == 0:
if i+1 == len(pattern):
matches.append(' '.join(text))
else:
success, match, text = matchWildcard(pattern[i+1], text)
if not success:
return False, []
else:
matches.append(match.strip())
We want to also be able to handle related meanings, which will help reduce a lot of redundant code. An example pattern with this might be:
[0,"I","am",0,["happy","glad","better"],0]
In this case we want to match “I am happy”, “I am glad”, and “I am better”, with the same responses. Here’s all of the code for the function.
ef matchPattern(pattern, text):
matches = []
for i in range(len(pattern)):
if pattern[i] == 0:
if i+1 == len(pattern):
matches.append(' '.join(text))
else:
success, match, text = matchWildcard(pattern[i+1], text)
if not success:
return False, []
else:
matches.append(match.strip())
elif len(text) == 0:
return False, []
elif not isinstance(pattern[i], str):
if text[0] in pattern[i]:
matches.append(text[0])
text = text[1:]
else:
return False, []
elif pattern[i] == text[0]:
matches.append(text[0])
text = text[1:]
else:
return False, []
return True, matches
Matching the wild cards
matchWildcard() function returns three values: a success/fail, the text matched, and the text remaining. One way to do this is through the use of recursion. We will use a soFar argument to keep track of what was matched. The function terminates when all the text is read or if the text matches with the term.
def matchWildcard(term, text, soFar=''):
if len(text) == 0:
return False, '', []
if (isinstance(term,str) and text[0] == term) or (not isinstance(term,str) and text[0] in term):
return True, soFar, text
return matchWildcard(term, text[1:], soFar + ' ' + text[0])
Testing the code
Now is a good time to test if the matchPattern() and matchWildCard() code works. We do that by creating a testPatterns() function above our main program to test for a variety of cases.
def testPatterns():
print(matchWildcard('stop', ['stop']))
print(matchWildcard('stop', ['stop', 'now']))
print(matchWildcard('stop', ['please', 'stop', 'now']))
print(matchWildcard('stop', ['please', 'I', 'stop']))
print(matchWildcard('stop', ['please', 'I', 'stop', 'now']))
print(matchWildcard('stop', ['please', 'I', 'finish', 'now']))
print(matchPattern([0, 'stop', 0], ['stop']))
print(matchPattern([0, 'stop', 0], ['stop', 'now']))
print(matchPattern([0, 'stop', 0], ['please', 'stop', 'now']))
print(matchPattern([0, 'stop', 0], ['please', 'I', 'stop']))
print(matchPattern([0, 'stop', 0], ['I', 'stop', 'right', 'now']))
print(matchPattern([0, 'stop', 0], ['I', 'can', 'finish', 'now']))
Here’s the resulting output:
(True, '', ['stop'])
(True, '', ['stop', 'now'])
(True, ' please', ['stop', 'now'])
(True, ' please I', ['stop'])
(True, ' please I', ['stop', 'now'])
(False, '', [])
(True, ['', 'stop', ''])
(True, ['', 'stop', 'now'])
(True, ['please', 'stop', 'now'])
(True, ['please I', 'stop', ''])
(True, ['I', 'stop', 'right now'])
(False, [])

Leave a Reply