#!/usr/bin/python import sys class WordTable: """ Describes a data structure that allows for easy and fast fetching of all the words that are different from a given word by exactly one letter """ def __init__(self): # A list whose index is the word with one letter replaced by its number self.prefixes = dict() # A list of prefixes that we only see for the first time self.pregatory = dict() # Also, a list of whole words - jsut for the validity checks self.words = set() def add_word(self, word): self.words.add(word) for i in xrange(len(word)): prefix = word[:i] + '.' + word[i+1:] if prefix not in self.pregatory: self.pregatory[prefix] = word else: if self.pregatory[prefix] == True: self.prefixes[prefix].append(word) else: self.prefixes[prefix] = [word, self.pregatory[prefix]] self.pregatory[prefix] = True def find_matches(self, word): """ Find all the words that differ from a given one by a single letter """ matches = [] for i in xrange(len(word)): prefix = word[:i] + '.' + word[i+1:] if prefix in self.prefixes: matches += self.prefixes[prefix] return matches def has_word(self, word): return word in self.words dictionary = WordTable() def read_dict(filename): f = open(filename) for line in f: dictionary.add_word(line.rstrip().lower()) f.close() def path(a, b): pending = [a] tried = {a : None} while len(pending) > 0: top = pending.pop(0) if top == b: chain = [] cur = top while cur != None: chain.insert(0, cur) cur = tried[cur] return chain for word in dictionary.find_matches(top): if word not in tried: tried[word] = top pending.append(word) return None def print_path(p): if p == None: print "ERROR: no path" return print ' > '.join(p), "(%d)" % len(p) def main(): read_dict(sys.argv[1]) while True: try: pair = raw_input("ENTER WORDS:").rstrip() words = pair.split(' ') if (len(words) != 2): print "ERROR: input must be two words separated by a space" continue if (len(words[0]) != len(words[1])): print "ERROR: words must be of the same length" continue if not dictionary.has_word(words[0]) or not dictionary.has_word(words[1]): print "ERROR: at least one of the words is not in the dictionary" continue p = path(words[0], words[1]) print_path(p) except EOFError: sys.exit() main()