I recently started reading the book Programming Pearls. It walks through several situations in software development which had interesting solutions. The solutions generally required a bit more thought about a problem than a person might initially give it, but were far simpler to write and/or more efficient than the first solution most people would think of as well.

This also includes exercises after each section which reinforce some of the concepts and ways of thinking used to solve the initial problem. I intend to do some of these and occasionally post my answers. The book used C++ and I may do some in C++ just for the experience. I'm more concerned with the higher level thought process and so will probably do most of these in Python, which is what I use most of the time these days, or possibly a different language which seems like it would be a good fit for the specific problem.

Here's the first one that I am posting.

phone_number_map.py:

from optparse import OptionParser
import re

# The book Programming Pearls has an excercise to code
# a simple algorithm for taking numbers pressed on a
# phone keypad and returning the names from a directory
# that the caller may have been looking for.  The book
# is really aimed at C and C++, but I'm doing some of these
# in Python since that's what I mostly work in these days
# and am building my skills in.

# Could have skipped the first two empty array elements
# and just remembered to subtract 2 to get the correct
# array element later.
phone_key_letters = [[],[],
                     ['a','b','c'],
                     ['d','e','f'],
                     ['g','h','i'],
                     ['j','k','l'],
                     ['m','n','o'],
                     ['p','q','r','s'],
                     ['t','u','v'],
                     ['w','x','y','z']]


def lookup_number(letter):
    for i in range(2, 10):
        if letter in phone_key_letters[i]:
            return i

def generate_word_map(wordfile, word_map):
    """Map words to the number combo that can create them"""
    f = open(wordfile, 'r')
    for word in f.readlines():
        word_number = ''
        i = 0
        for letter in word.strip().lower():
            word_number += str(lookup_number(letter))
            i += 1
            # Make this however many numbers the user would have entered
            if i == 3:
                break

        if word_number not in word_map:
            word_map[word_number] = []

        word_map[word_number].append(word.strip())

def lookup_words(word_map, phone_number):
    phone = re.sub(r'\D', '', phone_number)
    return word_map.get(phone, [])

if __name__ == '__main__':
    parser = OptionParser()
    parser.add_option("-f", "--file", dest="filename",
                      help="retrieve directory of names or words from FILE", metavar="FILE")
    parser.add_option("-n", "--number",
                      dest="phone_number",
                      help="phone number to lookup words for")

    (options, args) = parser.parse_args()

    # This could also be done with an array since the keys are all numbers.
    # The book uses C and C++ and the original implemenation probably was 
    # an array.  My data was pretty sparse, so I went with the
    # dictionary/hash instead.
    word_map = {}

    # In a real world app obviously this would be done once and the app
    # stays in memory or stores the mapping somewhere such as a db.
    generate_word_map(options.filename, word_map)

print lookup_words(word_map, options.phone_number)