This program functions like an anagram, the segment below shows a small algorithm which goes through a list of given words that are stored within a list named word_list
and compares the items within to a choice
word that is inserted by the user.
The first loop iterates through every one of those items within the list and assigns them to word
then sets shared_letters
(counter to decide whether or not the letters word
can be found within choice
) to zero before starting to go through shared letters between the two words in order to not overflow the i
iterable during the second loop.
The second loop iterates x
using the length of word
which is stored within word length
. Then the loop goes through a conditional if-statement which decides whether the x
index letter of sliced word
(which is just equal to list(word)
) is found within sliced choice
(list(choice)
). If it is then the counter shared_letters
goes up by 1, otherwise it breaks out of the second loop and goes back to the first in order to get a new word.
The looping process has worked fine before with me, but for some reason in this segment of code it just no longer runs the second loop at all, I've tried putting in print
statements to check the routes that the program was taking, and it always skipped over the nested for loop. Even when I tried turning it into something like a function, the program just refused to go through that function.
choice = input("Enter a word: ") # User enters a word
# Algorithm below compares the entered word with all the words found in the dictionary, then saves any words found into "sushi" list
for i in range(num_words): # Word loop, gives iterated word
word = word_list[i] # Picks a loop
shared_letters = 0 # Resets # of shared letters
for x in range(word_length): # Goes through the letters of iterated word
if sliced_word[x] in sliced_choice:
shared_letters = x 1
elif sliced_word[x] not in sliced_choice:
break
Here is the complete program just in case you want to get a better idea of it, sorry if the coding looks all jumbled up, I've been trying a lot with this program and I just seem to never reach a good solution.
word_list = ["race","care","car","rake","caring","scar"]
sushi = []
word = ""
sliced_word = list(word)
word_length = len(sliced_word)
choice_word = ""
sliced_choice = list(choice_word)
choice_length = len(sliced_choice)
shared_letters = 0
num_words = len(word_list)
next_word = False
choice = input("Enter a word: ") # User enters a word
# Algorithm below compares the entered word with all the words found in the dicitionary, then saves any words found into "sushi" list
for i in range(num_words): # Word loop, gives iterated word
word = word_list[i] # Picks a loop
shared_letters = 0 # Resets # of shared letters
for x in range(word_length): # Goes through the letters of iterated word
if sliced_word[x] in sliced_choice:
# Checks if the letters of the iterated word can be found in the choice word
shared_letters = x 1
elif sliced_word[x] not in sliced_choice:
break # If any of the letters within the iterated word are not within the choice word, it moves onto the next word
if shared_letters == word_length:
sushi.append(word_list[i])
# If all of the letters within the iterated word are found in the choice word, it appends the iterated word into the "sushi" list. Then moves onto the next word in the word_list.
CodePudding user response:
You have a number of issues, but I think the biggest is that this search does not account for anagrams that have multiple of the same letter. The easiest way to determine if a word would be an anagram or not would be to see if they each have the same count for each letter.
There is a builtin helper class called Counter
from the collections
module that can help with this.
>>> from collections import Counter
>>> Counter("care")
Counter({'c': 1, 'a': 1, 'r': 1, 'e': 1})
>>> Counter("race")
Counter({'r': 1, 'a': 1, 'c': 1, 'e': 1})
>>> Counter("care") == Counter("race")
True
Working this into your example, you could refactor like this:
word_list = ["race","care","car","rake","caring","scar"]
sushi = []
for word in word_list:
if Counter(choice) == Counter(word):
sushi.append(word)
Now this is kind of slow if we have to make the Counter objects over and over again, so you could choose to store them in a dictionary:
word_list = ["race","care","car","rake","caring","scar"]
word_counters = {word: Counter(word) for word in word_list}
sushi = []
for word, counter in word_counters.items():
if Counter(choice) == counter:
sushi.append(word)
If you want to find an imperfect match, say one word is contained in the other, you can use the -
operator and test if the lefthand side has any letters left over afterwards:
>>> not (Counter("race") - Counter("racecar"))
True
>>> not (Counter("race") - Counter("bob"))
False
Working that back into the example:
word_list = ["race","care","car","rake","caring","scar"]
word_counters = {word: Counter(word) for word in word_list}
sushi = []
for word, counter in word_counters.items():
if not (Counter(choice) - counter):
sushi.append(word)