Click Here to Install Silverlight*
United StatesChange|All Microsoft Sites
Microsoft TechNet*
Search Microsoft.com for:
|TechCenters|Downloads|TechNet Program|Subscriptions|Security Bulletins|Archive
Search for

2008 Winter Scripting Games

Solution to Advanced Perl Event 1: Could I Get Your Phone Number?

Event 1 Solution


Perl solution to Event 1 in the 2008 Winter Scripting Games.

Solutions are also available for VBScript and Windows PowerShell.

*

Could I Get Your Phone Number?


For the Scripting Guys, each and every Perl event in the 2008 Winter Scripting Games proved to be a real adventure; that’s because, up until just a few weeks before the Games began, the closest the Scripting Guys had ever come to Perl was a Perl T-shirt that the legendary Bob Wells (who coined the term “Scriptomatic”) gave Greg several years ago. And because that T-shirt didn’t include code that could convert a phone number to a word, well, it wasn’t all that useful, at least as far as the solutions go.

Although it does include code formatted to look like a camel. When you run that code, it prints out – that’s right, a picture of a camel!

And yes, that just might be an event in next year’s Scripting Games ….

That was one nice thing about Event 1: it required the Scripting Guys to put their … knowledge … of Perl to the test, and right away. Was our first Perl script something of the “Hello, world” variety? Not exactly; instead, our first Perl script included hash tables; reading from text files; generating random numbers; taking substrings from a string of characters; etc., etc. Is that the best possible way to learn Perl? Well, about all we can say is this: it’s one way to learn Perl.

At any rate, here is the first-ever Scripting Guys Perl script, a script that – not coincidentally –converts a phone number to a word:

%dictionary = ();

$dictionary{2} = "ABC";
$dictionary{3} = "DEF";
$dictionary{4} = "GHI";
$dictionary{5} = "JKL";
$dictionary{6} = "MNO";
$dictionary{7} = "PRS";
$dictionary{8} = "TUV";
$dictionary{9} = "WXY";

open (WordList, "C:\\Scripts\\WordList.txt");
@arrWordList = <WordList>;
close (WordList);

$strWordList = join(" ", @arrWordList);

print "Please enter the phone number: ";
$phonenumber = <>;

$low = 0;
$high = 3;

do
{
    $strCharacters = "";
 
    for ($i = 0; $i < 7; $i++)
        {
            $intValue = substr($phonenumber, $i, 1);
            $letters = $dictionary{$intValue};
            $b = int(rand($high) + $low);
            $substring = substr($letters, $b, 1);
            $strCharacters = $strCharacters . $substring
        }

if ($strWordList =~ m/$strCharacters/i)  
    {
        print $strCharacters;
        $x = 1;
    }
}
until $x == 1

As it turned out, writing the Perl scripts for the 2008 Winter Scripting Games wasn’t as hard as going back a couple weeks later, revisiting those scripts, and trying to remember why we wrote them the way we did. That’s what happens when you have a middling acquaintance with a scripting language.

Which simply means that we’ll do our best to explain how this particular script works. And if it turns out that our best isn’t all that good, well, now you know why.

Our script for Event 1 kicks off by creating a hash table (similar to a VBScript Dictionary object) named %dictionary; that’s what this line of code is for:

%dictionary = ();

Once we have our hash table, we then populate it by using this block of code:

$dictionary{2} = "ABC";
$dictionary{3} = "DEF";
$dictionary{4} = "GHI";
$dictionary{5} = "JKL";
$dictionary{6} = "MNO";
$dictionary{7} = "PRS";
$dictionary{8} = "TUV";
$dictionary{9} = "WXY";

All we’re doing here is adding the digits 2 through 9 as our hash table key; for the corresponding hash table item we’re adding the appropriate set of letters from the standard North American telephone dial. For example, this line of code creates a hash table entry with a key equal to 2 and a value equal to ABC:

$dictionary{2} = "ABC";

Once we have the hash table set up we use this chunk of code to open the text file C:\Scripts\WordList.txt, read the contents into an array named @arrWordList, and then close the file:

open (WordList, "C:\\Scripts\\WordList.txt");
@arrWordList = <WordList>;
close (WordList);

We should probably point out a couple of things when it comes to reading a text file in Perl. To begin with, we need to give our text file a sort of nickname, a way to reference it throughout the script. That’s what WordList is for in our first line of code:

open (WordList, "C:\\Scripts\\WordList.txt");

Notice, too that we need to “escape” each \ mark in the file path; that’s because the \ is a reserved character in Perl. A path like C:\\Scripts might look weird, but without doubling up the \’s the script will fail.

The long and short of it is this: line 1 tells the script to open the file C:\Scripts\WordList.txt, and to use the handle WordList to refer to that file. In line 2 we use standard Perl syntax to read the contents of WordList.txt (that is, the file referred to by the term WordList) and store those contents in an array named @arrWordList. (By default, each line in the file will be stored as a separate item in the array.) Finally, in line 3 we use the close function to close the file.

As you can see, it’s easy enough to read the contents of a text file and store those contents in an array; however, as far as we know it’s nowhere near that easy to search an array for a specified value (which we’ll have to do to determine whether we’ve created a real word out of our phone number). Because of that, our next step is to use the join function to join all the items in the array (that is, all the words in the text file) into a single string value, taking care to separate each word with blank spaces. That’s what this line of code is for:

$strWordList = join(" ", @arrWordList);

So are we ready now to try turning a phone number into a word? Well, not quite; after all, we don’t even know what the phone number is. To rectify that little problem, we use these two lines of code to prompt the user to enter a phone number, storing the entered value in a variable named $phonenumber:

print "Please enter the phone number: ";
$phonenumber = <>;

After that we assign the values 0 and 3 to the variable $low and $high, respectively:

$low = 0;
$high = 3;

We’re going to use these variables to randomly select a letter from a specified group of letters. (For example, the group ABC.) To choose a letter, we’ll specify the character position of that letter in the string, with A being character 0, B being character 1, and C being character 2. To pick a number between 0 and 2, inclusive, we set the low end of our range ($low) to 0 and the high end of the range ($high) to 3 (the last number in the range plus 1).

And guess what? Now we’re ready to try turning a phone number into a word.

OK, so then how do we turn a phone number into a word? To begin with, we set up a do loop designed to run until the variable $x is equal to 1 (until $x == 1). Inside that loop, we start things off by setting a variable named $strCharacters to an empty string:

$strCharacters = "";

After we’ve done that, we set up a for loop that starts at 0 and continues as long as the counter variable $i is less than 7:

for ($i = 0; $i < 7; $i++)

Why a loop that runs from 0 to 6? Well, as it turns out, a standard phone number has 7 digits, like this:

9737853

What we’re going to do is parse the phone number digit-by-digit, starting with the first digit (character position 0) and ending with the last digit (character position 6). In fact, that’s the first thing we do inside this for loop:

$intValue = substr($phonenumber, $i, 1);

Here we’re using the substr function to grab a single character from the phone number. What character are we grabbing? Well, the first time through the loop $i is equal to 0 so we’re going to grab character 0; in other words, the 9 in 9737853.

Of course, grabbing the first digit in the phone number is only a first step. Our next step is to use this line of code to grab the entry in the hash table corresponding to the number 9:

$letters = $dictionary{$intValue};

In other words, that’s going to make $letters equal to this: WXY.

And you’re right: WXY is only an interim step. What we need to do now is grab a single letter from that set of letters. To that end, we use this line of code to randomly select a number between 0 and 2, inclusive:

$b = int(rand($high) + $low);

Once we have that number we can then grab the designated character from the string $letters using this line of code:

$substring = substr($letters, $b, 1);

In other words, suppose we randomly generate the number 1. In that case, we’d use the preceding line of code to grab the letter in character position 1: the X. (Remember, the first character – W – is in character position 0.)

We then take that character and add it to the variable $strCharacters (note that the period is used to concatenate string values in Perl):

$strCharacters = $strCharacters . $substring

And then it’s back to the top of the loop, where we repeat the process with the next digit in the phone number. When all is said and done, we’ll end up with a seven-letter string value, with each letter corresponding to a digit in the phone number:

XPDPTJE

So is XPDPTJE a valid word? Well, there’s only one way to find out; we need to use the following line of code to see if XPDPTJE can be found anywhere in the string $strWordList:

if ($strWordList =~ m/$strCharacters/i)

Suppose the XPDPTJE can be found in $strWordList? In that case, this really is a word; in turn, we echo back the value of $strCharacters and then set the value of $x to 1:

print $strCharacters;
$x = 1;

And, of course, setting $x causes us to exit the original do loop, which also brings our script to an end.

But what if it turns out that XPDPTJE can’t be found in $strWordList? That means that we aren’t dealing with an actual word here; therefore, we go back to the top of the loop and repeat the process, randomly generating a new string from our phone number, then checking to see if that value is a real word. Eventually, our script should be able to randomly generate a string value that just happens to be a real word. For example, if the phone number is 9737853 we might end up with the following:

WRESTLE

Which was good enough for us.


 

© 2008 Microsoft Corporation. All rights reserved. Contact Us |Terms of Use |Trademarks |Privacy Statement
Microsoft