import time import sys import itertools #we're definitely going to need all of these things try: from collections_extended import bag except ModuleNotFoundError: print("Please install collections_extended by running this command: ") print("pip install collections_extended") print("If you have multiple python installations all bouncing around inside your OS, this is probably better:") print("[command you used to run this program (python3 for example)] -m pip install collections_extended") sys.exit() #collections_extended needs to be installed! def load_words(dictionary): with open(dictionary+".txt",errors="ignore") as word_file: #just guess what the files are called valid_words = word_file.read().split() return valid_words def sprint(string, time_): print(string) time.sleep(time_/2) #saves me the effort def enable_multiword(): global multiword_mode global word_count multiword_mode = True while True: preliminary_words = input("How many words should we check for? More takes longer > ") try: word_count = int(preliminary_words) break except: sprint("Please enter an integer", 0.5) sprint("Confirmed!",0.5) options.insert(0,multiword_off) options.remove(multiword) def switch_load(): global dictionary global wordlist while True: dictionary = input("Please enter the name of the dictionary you wish to use. Options are " + str(available_dictionaries) + " > ") if dictionary in available_dictionaries: wordlist = load_words(dictionary) break else: sprint("That's not right...", 0.3) print("Confirmed! ") def disable_multiword(): global multiword_mode multiword_mode = False options.insert(0,multiword) #keeps it at the right spot options.remove(multiword_off) sprint("Multiword mode disabled ", 0.3) def do_a_search(mode): global word_count global ridiculous while True: preliminary_scrambled_word = input("Please input a word (or words) which you would like to unscramble > ").lower().replace(" ","") if not preliminary_scrambled_word.isalpha(): sprint("Please input a word with letters only", 0.3) else: scrambled_word = preliminary_scrambled_word break scrambled_word_bag = bag(scrambled_word) found_anagrams = [] potential_anagrams = [] print("Wait one moment...") #I've written the same thing 4 times to save one if statement every loop. Which is probably a big difference. if mode == "normal": for word in wordlist: if bag(word) == scrambled_word_bag: #checks if all the letter counts are the same between this word and the other found_anagrams += [word] print(word,end="\r") #Show anagrams as they are found. Looks cool, serves no function. elif mode == "partial": for word in wordlist: if bag(word) >= scrambled_word_bag: #checks if the user's word could be in this word found_anagrams += [word] print(word,end="\r") elif mode == "containing": for word in wordlist: if bag(word) <= scrambled_word_bag: #checks if this word could be in the user's word found_anagrams += [word] print(word,end="\r") elif mode == "multiword": for word in wordlist: if bag(word) <= scrambled_word_bag: #checks if this word could be in the user's word potential_anagrams += [word] print(word,end="\r") if word_count > len(scrambled_word)*0.5: word_count = round(len(scrambled_word)*0.5) print("Reduced max word count to " + str(word_count)) #Two letters per word, no less! for n in range(1,word_count+1): #one word, two words, three words, four... print("Generating combinations of length " + str(n)) combinations = tuple(itertools.combinations(potential_anagrams, n)) #does what the previous print statement tells you it does. Can take an age. print("Testing those combinations...") if not ridiculous: #every way to add that many words for combination in combinations: #surely you can figure out what this does bag_neue = bag() #empty! sentence = "" #also empty! for word in combination: bag_neue += bag(word) #just chuck the letters into a bag sentence += (word + " ") #writes a beautiful sentence if bag_neue == scrambled_word_bag: #can we scramble the letters in these words to make the original one? found_anagrams.append(sentence) print(sentence,end="\r") else: for combination in combinations: if not((combination[0][0] != "s") and (combination[0][0] != "e") and (combination[0][0] != "v") and (combination[0][0] != "r") and (combination[0][0] != "g") and (combination[0][0] != "e")): if n > 1: found_anagrams.append(combination[0] + " " + combination[1]) else: found_anagrams.append(combination[0]) #found_anagrams = found_anagrams + combinations ridiculous = False if len(found_anagrams) > 1: sprint("I found these words for you: ", 0.3) for anagram in found_anagrams:#sorted(alphabetic,key=len): #sorts by length, then alphabetically. If we just sorted alphabetically, they'd go alphabetically and then by length, which is all wrong sprint(anagram, 1/len(found_anagrams)) #goes faster the more there are elif len(found_anagrams) == 1: sprint("I found one word!", 0.3) if found_anagrams[0] == scrambled_word: #these aren't bags sprint("it's just \"" + scrambled_word + "\" again, though...", 0.3) else: sprint("It's \"" + found_anagrams[0] +"\"! ", 0.3) else: sprint("I couldn't find anything...", 0.3) def partial_search(): do_a_search("partial") def standard_search(): if multiword_mode: do_a_search("multiword") else: do_a_search("normal") def containing_search(): do_a_search("containing") def ridiculous_search(): global ridiculous ridiculous = True do_a_search("multiword") ridiculous = False def exit_program(): print("Goodbye!") sys.exit() class option: def __init__(self, name, function, include = True): self.name = name self.function = function if include: options.append(self) #strictly unnessecary options = [] #change the defaults if you like multiword_mode = False dictionary = 'long' word_count = 3 available_dictionaries = ["short","long","names"] #if you add your own, put the file names (without .txt) in here multiword = option("Enable multiword mode to search for multiple-word results", enable_multiword, include = not multiword_mode) multiword_off = option("Disable multiword mode. ", disable_multiword, include = multiword_mode) load = option("Switch between dictionaries. Currently using ", switch_load) standard_find = option("Search for an anagram! ", standard_search) partial_find = option("Search for words containing the letters in a word", partial_search) # can be used to cheat at countdown containing_find = option("Search for words contained in a word", containing_search) special_find = option("Search for multiple words contained in a word?",ridiculous_search) exit = option("Exit the program ", exit_program) assassins = False #don't worry about it wordlist = load_words(dictionary) while True: i = 0 for thing in options: if thing != load: #special exception sprint("["+str(i)+"] "+thing.name,0) else: sprint("["+str(i)+"] "+thing.name+dictionary+".",0) i += 1 while True: try: choice = int(input("> ")) break except ValueError: print("Please enter an integer") options[choice].function() sprint("Back to the menu... ",1)