skip navigation
 
 
 
WebInSight
Previous

Regular Expressions

Basic Matching with Regular Expressions

Regular expressions can be used as tests to replace the == and != operators on strings that we learned about previously. Like these constructs, they are also used in conditional statements. We use the User.RegexMatch method and give it two parameters: the regular expression (a string), and the message to match against. The following is an example regular expression that will be true if the string variable input contains the word "hello" anywhere within it.

if (User.RegexMatch("hello", message)) {
	return "hi there!";
} else {
	return "hello! hello! Is anyone there?";
}

Here is the full source for this example: BasicRegexExampleBot.cs

Regular Expressions Exercise 1

To use your new knowledge of regular expressions, build the following Simon Says program. Your program should act as someone playing the game Simon Says. The person messaging the bot will be Simon. Your chatbot should respond "I did it!" if command contains the string "Simon Says" and it should respond "I will not do it, Simon-impersonator!" otherwise. If you get stuck, here is the solution: SimonSaysBot.cs.

More Powerful Regular Expressions

Regular expressions are powerful and can be used to test for more complicated constructions. For example, what if we want to test to see if our string contains either "Hi", "Hello", or "Howdy"? We can do this by creating a regular expression that matches any of these phrases. We do this by connecting the different options for strings to look for by the | character, resulting in the regular expression "Hi|Hello|Howdy". In code this looks like the following:

if (User.RegexMatch("Hi|Hello|Howdy", message)) {
	return "Success!";
} else {
	return "Failure.";
}

Here is the full source for this example: PowerfulRegex1Bot.cs

Sometimes, you want to optionally match part of the string. For instance, what if you wanted to select out "cow" and "cows" but not "cowboy"? You can use the question mark (?) to indicate that the part of the expression that came before the ? is optional. In this example, "cows?" says to definitely match the "cow" part and to optionally match the "s".

Regular expressions can also group parts of the expression, which is useful in conjunction with optionally matching pieces of the regular expression. The following regular expression will match both "Mr. Chatbot" and "Chatbot".

if (User.RegexMatch("(Mr. )?Chatbot", message)) {
	return "Success!";
} else {
	return "Failure.";
}

Here is the full source for this example: PowerfulRegex2Bot.cs

In the regular expression "(Mr. )?Chatbot", the characters in "Mr. " (notice the space after Mr.) are grouped together using parentheses and a question mark is added after the closing parenthesis to indicate that the "Mr. " is optional.

Regular Expressions Exercise 2

As a final text of your mastery of regular expressions, create a chatbot so that it responds "Barnyard animal!" if the message received contains any of the following three barnyard animals "cow", "horse" and "pig" and their plurals "cows", "horses", "pigs". Otherwise, the chatbot should respond: "Not a barnyard animal...". Are there multiple ways to write a regular expression that matches these strings?

Solution: RegexExercise2Bot.cs

Advanced Regular Expressions

The syntax allowed in regular expressions is far to vast to be within the scope of this tutorial. If you're interested, check out the more extensive regular expression tutorial provided by Jan Goyvaerts.

Remembering and Reacting

At this point, you've learned how to enable your chatbots to make decisions; they can decide how to respond to you based on what you wrote to them. A vital component of intelligence is remembering and learning. In this section, you'll learn to give your chatbots the ability to remember things.

Variables that don't disappear

In an earlier part of this tutorial, you created variables that held strings. These variables were nice, but once your bot returned a message the value stored in the variable could no longer be accessed. In this section, you'll use the FlatFile parameter of the HandleMessage method to allow your chatbot to store a value that will stay around. This object is really a new kind of variable. So, if you set ff["key"] equal to the string "value", ff["key"] will be equal to "value" the next time you access it, just like a regular variable that you've already learned about. Under the covers the FlatFile object stores the values in your variables on your computer's hard drive.

Consider the following example:

ff["lastMessage"] = message;

In the preceeding example, we created a new variable called ff["lastMessage"] and set it equal to the parameter variable message. There's nothing special about the "lastMessage" string that we used, we could have used "myMessage" or "purpleElephant" instead. That string just lets us refer to the value message by that name later.

Try creating a chatbot that will respond to the user with the message that they wrote last time. This is similar to BouncerBot, except that instead of replying with the message just written by the user, the bot will store the message written by the user last time and reply with that. If you get stuck or if you want to verify your code, look at the LastMessageBouncerBot Solution.

Remembering State

What is state? If you're sitting at a computer, part of your state is just that - sitting at a computer. But that's just one component of your state. You're also awake, a person, tired, happy, wondering when this list will stop so you can get back to coding chatbots. All of these provide information about your current condition, your state. Information like this is handy to have around when making intelligent decisions. For instance, if my state includes the fact that I'm standing beside a cliff, I'm better able to made an informed decision about whether to start practicing my spinning long jump. Without that information, I might end up a pancake on a canyon floor.

In a conversation, it's similarly handy for your chatbot to remember what it's said so it can expect the responses that it gets. If someone writes the message "three" to your chatbot out of the blue, it might respond with a generic greeting like "Hello random person". If your chatbot had remembered that it had just asked them how many chocolate sundaes they ate at dinner last night, however, it could have replied with something much more intelligent, like "Wow, that's a lot of ice cream!" Remembering relevant state information will help your chatbots seem more intelligent and now you have the tools to give this capability.

Write a chatbot starts off by asking "How are you doing?" but responds "Glad to hear it." if it's expecting to hear how someone's doing. If you get stuck, view the HowAreYouDoingBot Solution.

Nested Conditionals and State

Nested conditionals are conditional statements that appear within the blocks of code defined by other conditionals. Computer scientists say they "nest," just like sets of parentheses are said to nest within one another in a mathematical expression like (6*(3+4))/7. Nested conditionals are handy to use when you're keeping track of state because often you'll want to first check on a feature in your state and then decide how to respond. For instance, a chatbot could check to see if it's in a state that's expecting the user to respond with how many ice cream sundaes they ate last night and then choose how to respond based on what they just said. The following example, does just that:

if(ff["responseState"] == "asked about ice cream") {
  ff["responseState"] = "";
  if(message == "none") {
    return "None?  That's crazy!";
  } else if(message == "one") {
    return "One is a good number.  Everything should be done in moderation.";
  } else {
    return "Wow, that's a lot!";
  }
} else {
  ff["responseState"] = "asked about ice cream";
  return "How many ice cream sundaes did you eat last night at dinner?";
}

In this example, the chatbot first checks to see if the variable ff["responseState"] contains the string "asked about ice cream". If it does, then the chatbot starts executing the code in the block of code associated with the if. It first resets ff["responseState"] to nothing by setting it equal to the empty string "". This will prevent the bot from thinking that it just asked about ice cream the next time it receives a message. It then enters the nested conditional to decide what response it should send back to the user.

But how did the ff["responseState"] variable get set to "asked about ice cream" in the first place? That happens in the else block of the outer conditional that tests what state we're in. If ff["responseState"] is not equal to "asked about ice cream" then it executes the following two lines of code located in the else block:

  ff["responseState"] = "asked about ice cream";
  return "How many ice cream sundaes did you eat last night at dinner?";

The first line sets the state to "asked about ice cream" so that they next time the bot has to respond to a message, it will know that it just asekd about ice cream. Then it actually asks the question. It's important that ff["responseState"] is set before returning the message because otherwise that statement won't get executed and the chatbot will not remember its state.

Now try creating your own chatbot that uses state and nested conditionals. Expand your HowAreYouDoingBot from above to choose among several responses after it receives a reply to how the user is doing. For example, if the user replied "good" your chatbot can respond "Glad to hear it." If they say bad, your chatbot could return an empathetic response like "Oh, I'm so sorry to hear that." (as all good chatbots should). You might even want to try adding in regular expression matching for more flexible matching of user responses. Feel free to personalize your chatbot to make it extra happy, mean, empathetic, apathetic, rude, etc. While there are many acceptable solutions and variations to this exercise, if you get stuck view the NestedConditionalsHowAreYouDoing Solution.

Web Services

Now that your chatbots can remember what you tell them, wouldn't it be great if they could also tell you something you didn't know? Perhaps, your chatbot could make a comment on the weather, suggest a recipe to make or tell you the latest breaking news. All this can be done by having your chatbot browse through handy web services called RSS feeds.

RSS feeds

Similar to a radio stations, RSS feeds are meant for broadcasting information that frequently changes and updates. Each entry in a RSS feed has a title, a link and a description. Programs go and collect information and bring it back to the user. For our purposes, we will simply call a method to get the information we want.

Using Provided Web Services

Getting the weather

Let's start off with getting the weather for today. To do so we can call a method named User.RSSWeatherToday. This method has two parameters: the city and the state in which you want the weather from. To use it, just give it the parameters for the location you want and store the answer in a variable. For example, if you wanted the chatbot to check the weather in Baltimore, Maryland you might code something like this:

string weather = User.RSSWeatherToday("Baltimore", "Maryland");
return weather;

Notice that "Baltimore", the city, came before "Maryland", the state. This ordering is important because if you flipped these two around the poor chatbot will go off looking for a city named Maryland in Baltimore state which doesn't exist!

Browsing the news

Aside from getting the weather, you can also search on Google News for interesting news related to a given topic. The methods for doing this are the following:

User.RSSGoogleNewsTitle( string searchTerm )
Gets the title of the news item.
User.RSSGoogleNewsLink( string searchTerm )
Gets the link to the full article.
User.RSSGoogleNewsDescription( string searchTerm )
Gets a brief description of the news.

The parameter named searchTerm is a string that contains the keywords to perform the search by. For example, the following code makes a handy bot that will give you a link the top headline related to what you just said to it:

string link = User.RSSGoogleNewsLink( message );
string title = User.RSSGoogleNewsTitle( message );
return "I've heard some news about that. It was called: "+ title +". Check it out at: " + link;

So if I say "I like smoothies" to this bot, It might reply with the following:

I've heard some news about that. It was called:
Beat the Heat With Refreshing Summer Treats - Korea Times. 
Check it out at: http://news.google.com/news/url?sa=T&
ct=us/0-0&fd=R&url=http://www.koreatimes.co.kr/www/
news/art/2007/07/203_7196.html&cid=0&ei=9SmpRtCnGaGeqwPjv_2WDg

Customizing your own Services

If you wish to go far and beyond the world of weather and Google News, you can get information from an RSS feed of your choice. First you need to find the url to a RSS feed you wish to use. These can be found online at sites similar to Top 100 Most-Subscribed-To RSS Feeds. Once you get a RSS feed url, you can call the functions User.RSSgetTitle, User.RSSgetLink and User.RSSgetDescription with the url as the first parameter and get the information you would like.

If you would like to know what other methods you can call to get specific RSS information, check out the RSS Reference.

Previous
 
Comments to Jeffrey P. Bigham