Phone Number Conversion Challenge
Even though the1 already posted the his solution to his programming challenge, I was already amidst my own solution to it when he posted his.
I didn't think I was going to take a stab at it, since I figured plenty of other people would. But as I saw people posting their solutions, it seemed like one thing was consistent in that most of them were taking the number, looking at how many ways the number could be represented as a string and then check if it was a word.
Then I thought, “what if you did it the other way around?” What if you take a word, get its numerical form, and see if it was in the phone number. Main reason being, a sequence of numbers has many possible string forms, but a word only has one possible numerical form. I should note though that this is rather inefficient. I used the basic English word list the1 posted, which was about 850 words. It was rather limited since in his challenge post, he had an example number with a possible output of “nice-window”, but the word list didn't even have “nice“. As your dictionary grows, it gets slower and slower. Example being I took some of the dictionary files from ispell (unix spell checker) so it had a little over 100,000 entries. Yeah, slow. Eventually, the number of possible strings the number can be is less than the amount of time you'll spend looping through the dictionary. I did it just to see how it'd work though. Here is my “solution” in C#:
using System;
using System.Collections;
using System.IO;
namespace PhoneWord
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Finder
{
static ArrayList dictionary = new ArrayList();
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
string phoneNumber = "6423946369"; // The phone number
// Load the dictionary
LoadDictionary("dictionary.txt");
FindWord(phoneNumber); // Start finding them words!
}
/// <summary>
/// This function loops through the dictionary, converts the words to their
/// numerical form, and then looks for a match in the phone number. If there is a
/// match, it replaces the numbers with the word, and then calls itself to find
/// another word match.
/// </summary>
/// <param name="phoneNumber">The current phone number and any word matches already found.</param>
static void FindWord(string phoneNumber)
{
foreach(string word in dictionary)
{
string tempNumber = phoneNumber;
string metanumber = ConvertToMetanumber(word);
if(tempNumber.IndexOf(metanumber) >= 0)
{
tempNumber = tempNumber.Replace(metanumber, word);
Console.WriteLine("answer: " + tempNumber);
FindWord(tempNumber);
}
}
}
/// <summary>
/// This function loads all the entries from a dictionary file into an array list.
/// The file is formatted with 1 word per line.
/// </summary>
/// <param name="filename">The filename of the dictionary file.</param>
static void LoadDictionary(string filename)
{
StreamReader file = new StreamReader(filename);
while(file.Peek() >= 0)
{
string word = file.ReadLine();
if((word.Length < 10) || (word.IndexOf("'") == -1) || (word.Length != 0))
dictionary.Add(word);
}
file.Close();
}
/// <summary>
/// This function converts a word into its numerical representation.
/// </summary>
/// <param name="word">The word to be converted.</param>
/// <returns>string</returns>
static string ConvertToMetanumber(string word)
{
if(word == "")
return "";
else
{
// get a number referencing the char (A=0, B=1, C=2, ... Z=25)
int asciiChar = Convert.ToInt32(Convert.ToChar(word.Substring(0, 1).ToUpper())) - 65;
if(asciiChar > 17) asciiChar--; // Trim it down by one after R, since 7 is PRQS
if(asciiChar > 23) asciiChar--; // Trim it down by one more if Z, since 9 has WXYZ
int asciiNumber = (asciiChar / 3) + 50; // Divide by 3 to get which number it is on, add 50 for ASCII index
return Convert.ToString(Convert.ToChar(asciiNumber)) + ConvertToMetanumber(word.Substring(1, word.Length-1));
}
}
}
}