#!/usr/bin/python """ This program analyzes the a text that is given to it, counting every individual word. It is then able to report on them to the user. It can also give basic statistics on the hash table, such as its size, load factor, etc. It relies on a HashTable object, that you must write. The API is as given in the assignment. """ __author__ = "Adam A. Smith" __version__ = "2023.09.28" from hashtable import HashTable import re # load a file & make a HashTable from its words def _make_hash_table(filename:str) -> HashTable: hash_table = HashTable() with open(filename) as file: for line in file: tokens = re.split(r"[^A-Za-z0-9'_]+", line.lower()) for token in tokens: # remove leading/trailing apostrophes if token.startswith("'"): token = re.sub(r"^'+", "", token) if token.endswith("'"): token = re.sub(r"'+$", "", token) # skip if it was just apostrophes or otherwise empty if len(token) == 0: continue # add to table if (hash_table.contains_key(token)): freq = hash_table.get(token) + 1 hash_table.put(token, freq) else: hash_table.put(token, 1) return hash_table # enter a loop to query the user for searches & commands def _query_user(hash_table : HashTable): print("The text contains " +str(len(hash_table))+ " unique words.") print('Please enter a word to query, or "!help" for help, or "!exit" to exit.') while True: print("> ", end="") query = input() # do nothing on empty string if len(query) == 0: pass # quit on "!quit" or "!exit" elif query == "!quit" or query == "!exit": break # check for size elif query == "#": print("The text contains " +str(len(hash_table))+ " unique words.") # print stats on the backing table elif query == "!stats": print("Hash table statistics:") print("\tSize (n): " +str(len(hash_table))) print("\tTable size (m): " +str(hash_table.get_table_size())) print("\tLoad factor (α):", "{:1.3f}".format(hash_table.get_load_factor())) print("\tEmpty units: " +str(hash_table.count_empty_slots())) print("\tLongest run: " +str(hash_table.find_longest_run())) # help menu elif query == "!help": _print_help_menu() # unknown special command elif query.startswith("!"): print("I didn't recognize that. Try \"!help\"?") # deletion elif query.startswith("-"): word_to_delete = query[1:] if len(word_to_delete) == 0: print("What word do you want to delete? Please try again.") else: value = hash_table.delete(word_to_delete) if (value is None): print('"' +word_to_delete+ '" was not present.') elif value == 1: print('1 entry of "' +word_to_delete+ '" has been deleted.') else: print(str(value) + ' entries of "' +word_to_delete+ '" have been deleted.') # add a word or increase its frequency elif query.startswith("+"): new_word = query[1:] if len(new_word) == 0: print("What word do you want to add? Please try again.") elif hash_table.contains_key(new_word): freq = hash_table.get(new_word) + 1 hash_table.put(new_word, freq) print('"' +new_word+ '" now appears ' +str(freq)+ '×.') else: hash_table.put(new_word, 1) print('"' +new_word+ '" now appears 1×.') # regular query else: freq = hash_table.get(query) if freq is None or freq == 0: print('"' +query+ '" is not in the text.') else: print('"' +query+ '" appears ' +str(freq)+ '× in the text.') print("Goodbye!") # just prints a help menu def _print_help_menu(): print("\t\t\tprints word frequency") print("\t-\t\tdeletes word") print("\t+\tadds word") print("\t#\t\tprints the table size") print("\t!help\t\tprints this help menu") print("\t!stats\t\tprints in-depth stats on the table") print("\t!exit\t\texits the program") # pseudo main() function if __name__ == "__main__": # test command-line args from sys import argv, exit, stderr # make sure we have a file if len(argv) != 2: print("Please enter a file name!", file=stderr) exit(0) # make the hash, and query on it try: hash_table = _make_hash_table(argv[1]) _query_user(hash_table) except FileNotFoundError: print("Couldn't open file \"" +argv[1]+ "\".", file=stderr) exit(1)