# Programmer: 22C:16 class # Date: 4/4/13 # Version 1 # This program reads a list of 5-letter words from a file called words.dat. It then builds a dictionary # of these words. Each word is a key in the dictionary. The neighbors of a word w are all those words that # differ from it in exactly one letter. The value associated with a key w in the dictionary is the list # of neighbors of that word. The program then reads two 5-letter words: source and target and explores # the dictionary to determine if there exists a chain of words connecting the source to the target. # This version of the program will not output a chain - just tell us that a chain exists. import time # Two words are neighbors if they differ in exactly on letter. # This function returns True if a given pair of words are neighbors def areNeighbors(w1, w2): count = 0 for i in range(len(w1)): if w1[i] != w2[i]: count = count + 1 return count == 1 # The function reads from the file "words.dat" and inserts the words that are read # into a list. The words are also inserted into a dictionary as keys, with each key # initialized to have [] as its value. def readWords(wordList, D): fin = open("words.dat", "r") # Loop to read words from the and to insert them in a list # and in a dictionary for word in fin: newWord = word.strip("\n") wordList.append(newWord) D[newWord] = [] fin.close() # Builds the network of words using a dictionary. Two words are connected by an edge in this # network if they are neighbors of each other, i.e., if they differ from each # other in exactly one letter. def buildDictionary(wordList, D): # Constructing wordMatrix wordMatrix = [[] for i in range(26)] for w in wordList: wordMatrix[ord(w[0])-ord("a")].append(w) # Constructing suffixes suffixes = [[w[1:], w[0]] for w in wordList] suffixes.sort() # Constructing type (i) neighbors for i in range(26): for j in range(len(wordMatrix[i])): for k in range(j+1, len(wordMatrix[i])): if areNeighbors(wordMatrix[i][j], wordMatrix[i][k]): D[wordMatrix[i][j]].append(wordMatrix[i][k]) D[wordMatrix[i][k]].append(wordMatrix[i][j]) # Constructing type (ii) neighbors for i in range(len(suffixes)): word1 = suffixes[i][1] + suffixes[i][0] j = i + 1 while j < len(suffixes) and suffixes[i][0] == suffixes[j][0]: word2 = suffixes[j][1] + suffixes[j][0] D[word1].append(word2) D[word2].append(word1) j = j + 1 # Explores the network of words D starting at the source word. If the exploration ends # without reaching the target word, then there is no path between the source and the target. # In this case the function returns False. Otherwise, there is a path and the function # returns True. def searchWordNetwork(source, target, D): # Initialization: processed and reached are two dictionaries that will help in the # exploration. # reached: contains all words that have been reached but not processed. # processed: contains all words that have been reached and processed, i.e., their neighbors have also been explored. # The values of keys are not useful at this stage of the program and so we use 0 as dummy values. processed = {source:0} reached = {} for e in D[source]: reached[e] = 0 # Repeat until reached set becomes empty or target is reached while reached: # Check if target is in reached; this would imply there is path from source to target if target in reached: return True # Pick an item in reached and process it item = reached.popitem() # returns an arbitrary key-value pair as a tuple newWord = item[0] # Find all neighbors of this item and add new neighbors to reached processed[newWord] = 0 for neighbor in D[newWord]: if neighbor not in reached and neighbor not in processed: reached[neighbor] = 0 return False # Main program start = time.time() wordList = [] D = {} readWords(wordList, D) buildDictionary(wordList, D) end = time.time() print(end - start) source = input("Please type the source word: ") target = input("Please type the target word: ") if searchWordNetwork(source, target, D): print("There is path from source to target") else: print("There is no path from source to target")