From 9214cdea097a3cc966a0993ea34bb5abba8f5588 Mon Sep 17 00:00:00 2001 From: cdez Date: Sun, 2 Feb 2025 15:11:51 -0700 Subject: [PATCH] add the next Boggle part. --- Boggle/03_test.py | 120 ++++++++++++++++++++++++++++++++++++++++-- Boggle/interpreter.py | 23 ++++++++ 2 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 Boggle/interpreter.py diff --git a/Boggle/03_test.py b/Boggle/03_test.py index ca24259..bec6733 100644 --- a/Boggle/03_test.py +++ b/Boggle/03_test.py @@ -1,3 +1,5 @@ +import time + def loadBoard(fileName): with open(fileName) as board: boardContents = board.read() @@ -25,10 +27,122 @@ def possibleMoves(inputCoords, boardInput): if (0 <= newX <= maxLen) and (0 <= newY <= maxLen): moveList.append((newX, newY)) - print(moveList) - # return moveList + # print(moveList) + return moveList + +def legalMoves(possMoves, pathTaken): + legalMoveSet = set(possMoves) + pathTakenSet = set(pathTaken) + return legalMoveSet.difference(pathTakenSet) + +def readDictionary(fileName): + wordList = [] + with open(fileName) as words: + wordList = words.read().splitlines() + return wordList + +def examineState(boardInput, inputCoords, pathTaken, wordList): + # add the inputCoords to the pathTaken + pathTaken = pathTaken + (inputCoords,) + # find the word that is associated with that path + createdWord = "" + for x, y in pathTaken: + createdWord = createdWord + boardInput[x][y] + createdWord = createdWord.lower() + # check the wordList to see if that word is valid + validWord = createdWord in wordList + # create a tuple that includes the word, and 'Yes' if the word was valid. + validState = "No" + if validWord: + validState = "Yes" + state = (createdWord, validState) + # return the created tuple + return state + +def runBoard(boardFileName, wordListFileName): + # load the board + completeBoard = loadBoard(boardFileName) + # load the dictionary + completeDictionary = set(readDictionary(wordListFileName)) + # print out the board + printBoard(completeBoard) + # print out the starting + print("\nAnd we're off!") + # count the number of paths that are searched + searchedPaths = 0 + # define a set of the found words + foundWords = set() + # since the board is square, take the length of the board from one side. + boardSize = len(completeBoard) + # start the time counter + startTime = time.time() + # use a double for loop structure to traverse the board + for x in range(boardSize): + for y in range(boardSize): + # define the current traced path, using a tuple, inside a set, inside a set, inside a list... + # this was a very frustrating structure to work with... + trace = [((x, y),)] + # now, using a while loop, go through the trace structure. + while trace: + # this is the current path taken, remove it from the list + currentPath = trace.pop() + # add the number of paths + searchedPaths = searchedPaths + 1 + # save the previous coordinate used from the current path + previousCoord = currentPath[-1] + # add a possible path using the possible moves function. + possiblePath = possibleMoves(previousCoord, completeBoard) + # check which are the legal moves/paths + legalPath = legalMoves(possiblePath, currentPath) + # now, check each path within the legalPath structure + for path in legalPath: + # add the path to a temporary variable + newPath = currentPath + (path,) + # check to see if the word is valid, deconstructing the tuple + # into the word and if the word exists using the examineState + # function + checkWord, validWord = examineState(completeBoard, path, currentPath, completeDictionary) + # check to see if the word is valid, and if it is, + # then add that word to the foundWords set. + if validWord == "Yes": + foundWords.add(checkWord.upper()) + # append the path to the trace tracker. + trace.append(newPath) + # save the current time as the endTime + endTime = time.time() + # subtract the endTime and startTime to get the total amount of time + totalTime = endTime - startTime + # tell the user that the search is complete. + print("All done") + # print out how many paths were searching and how long it took + print(f"\nSearched total of {searchedPaths} moves in {totalTime:.3f} seconds") + # print out how many word were found of each length, comma separated, + # using a empty dictionary. + wordLens = {} + # loop through the foundWords list + for word in foundWords: + # set the current word length + length = len(word) + # check to see if the length is within the dictionary + if length not in wordLens: + wordLens[length] = [] + # append the word to dictionary associating it with a length + wordLens[length].append(word) + # show the words that are found + print("\nWords found:") + # loop through the total length, and the words that are now sorted in the + # wordLens dictionary. + for length, words in sorted(wordLens.items()): + # print out each word list, creating the string kinda on the fly. + print(f"{length}-letter words: {', '.join(sorted(words))}") + # print out the number of words found total + print("\nFound " + str(len(foundWords)) + " words in total.") + # print out an alphabetical sorted list of the words (comma separated) + print("Alpha-sorted list words:") + print(", ".join(sorted(foundWords))) + +# (DONE) define runBoard and other functions. -# TODO define runBoard and other functions. runBoard("board2.txt", "twl06.txt") runBoard("board3.txt", "twl06.txt") runBoard("board4.txt", "twl06.txt") diff --git a/Boggle/interpreter.py b/Boggle/interpreter.py new file mode 100644 index 0000000..c6b38b7 --- /dev/null +++ b/Boggle/interpreter.py @@ -0,0 +1,23 @@ +import code +import re +class FileConsole(code.InteractiveConsole): + """Emulate python console but use file instead of stdin""" + def raw_input(self, prompt): + line = self.f.readline() + if line=="": + raise EOFError() + no_newline = line.replace("\n", "") + no_indent = re.match(r"^\s", line) is None + print(prompt, no_newline, sep="") + return no_newline + +def run_file(filename): + fc = FileConsole() + fc.f = open(filename) + fc.interact(banner="", exitmsg="") + +if __name__ == "__main__": + import sys + sys.ps1 = "\n>>> " + run_file(sys.argv[1]) +