My anagram code doesn't account for multiple letters - python

So my code gets two words, and checks if one is the anagram of another one.
However doesn't work if multiple letters are exchanged, although I tried to account for that.
storedword = input("Enter your primary word \t")
global word
word = list(storedword)
word3 = input("Enter anagram word \t")
word3lowercase = word3.lower()
anaw = list(word3lowercase)
counter = int(0)
letterchecker = int(0)
listlength = len(word)
newcounter = int(0)
if len(anaw) != len(word):
print ("not anagram")
if len(anaw) == len(word):
while counter < listlength and newcounter < listlength:
tempcount = 0
if anaw[counter] == word[newcounter]:
temp = word[newcounter]
word[newcounter] = word[tempcount]
word[tempcount]=temp
letterchecker +=1
counter +=1
tempcount +=1
newcounter = int(0)
else:
newcounter +=1
if counter == len(word):
print ("anagram")
else:
print ("not anagram")
I think it's gone somewhere wrong after the if len(anaw) section, for example if the primary word is "hannah", and the secondary word is "hannnn", it thinks it's an anagram.

There is much simpler logic that can be implemented here, even without using sorted and such. Let's assume you have a function anagram:
def anagram(word1, word2):
if len(word1) != len(word2):
return False
def char_count(word):
char_count = {}
for c in word:
char_count[c] = char_count.get(c, 0) + 1
return char_count
cr1 = char_count(word1)
cr2 = char_count(word2)
return cr1 == cr2
You can test this with:
>>> print(anagram("anagram", "aanragm"))
True
>>> print(anagram("anagram", "aangtfragm"))
False
And for future readers, a super simple pythonic solution might be using Counter:
from collections import Counter
>>> Counter(word1) == Counter(word2)
Or using sorted:
>>> sorted(word1) == sorted(word2)

newcounter = int(0)
This is the line that causes the trouble (in the while loop).
Because of it you start checking the word from the beginning again.
I think you want it to be newcounter=letterchecker.
Since already used characters are put to the front of word they are ignored if you start with letterchecker
Tell me if it works
Edit:Checked with example given, seems to work.

Without using sort you could use the following approach. It removes a letter from an array of a characters of the second word. The words are only anagrams if there are no letters left (and the words are the same length to start with and have a length larger than zero):
word1="hannah"
word2="nahpan"
chars1= list(word1)
chars2= list(word2)
if len(chars1)==len(chars2) and len(chars1)>0:
for char in chars1:
if char not in chars2:
break
chars2.remove(char)
if len(chars2)==0:
print "Both words are anagrams"
else:
print "Words are not anagrams"

[EDIT THIS IS JUST FOR PALINDROMES I CANT READ]
Here is something a bit more simple:
storedword = input("Enter your primary word \t")
word3 = input("Enter anagram word \t")
if storedword == word3[::-1]:
print "Is Anagram"
else:
print "Is not anagram"

Related

Find words in a string of text (where letters aren't consecutive)

I'd like write code to find specific instances of words in a long string of text, where the letters making up the word are not adjacent, but consecutive.
The string I use will be thousands of characters long, but a as a shorter example... If I want to find instances of the word "chair" within the following string, where each letter is no more than 10 characters from the previous.
djecskjwidhl;asdjakimcoperkldrlkadkj
To avoid the problem of finding many instances in a large string, I'd prefer to limit the distance between every two letters to 10. So the word chair in the string abcCabcabcHabcAabdIabcR would count. But the word chair in the string abcCabcabcabcabcabcabcabcabHjdkeAlcndInadhR would not count.
Can I do this with python code? If so I'd appreciate an example that I could work with.
Maybe paste the string of text or use an input file? Have it search for the word or words I want, and then identify if those words are there?
Thanks.
This code below will do what you want:
will_find = "aaaaaaaaaaaaaaaaaaaaaaaabcCabcabcHabcAabdIabcR"
wont_find = "abcCabcabcabcabcabcabcabcabHjdkeAlcndInadhR"
looking_for = "CHAIR"
max_look = 10
def find_word(characters, word):
i = characters.find(word[0])
if i == -1:
print("I couldnt find the first character ...")
return False
for symbol in word:
print(characters[i:i + max_look+1])
if symbol in characters[i:i + max_look+1]:
i += characters[i: i + max_look+1].find(symbol)
print("{} is in the range of {} [{}]".format(symbol, characters[i:i+ max_look], i))
continue
else:
print("Couldnt find {} in {}".format(symbol, characters[i: i + max_look]))
return False
return True
find_word(will_find, looking_for)
print("--------")
find_word(wont_find, looking_for)
An alternative, this may also work for you.
long_string = 'djecskjwidhl;asdjakimcoperkldrlkadkj'
check_word = 'chair'
def substringChecker(longString, substring):
starting_index = []
n , derived_word = 0, substring[0]
for i, char in enumerate(longString[:-11]):
if char == substring[n] and substring[n + 1] in longString[i : i + 11]:
n += 1
derived_word += substring[n]
starting_index.append(i)
if len(derived_word) == len(substring):
return derived_word == substring, starting_index[0]
return False
print(substringChecker(long_string, check_word))
(True, 3)
To check if the word is there:
string = "abccabcabchabcaabdiabcr"
word = "chair"
while string or word:
index = string[:10].find(word[0])
if index > -1:
string = string[index+1:]
word = word[1:]
continue
if not word:
print("found")
else:
break

Improve the odds of winning at hangman with ai

I'm new (and to stack overflow, this is the first question I have ever asked) to python, I have been self-teaching myself for a couple of weeks. I was doing some beginner projects when I decided to make a hangman ai.
#importing
import random
import time
import sys
from collections import Counter
#---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#defining some variables
list_of_words = open("dictionary.txt", "r")
list_of_words = list_of_words.read().split()
SYMBOL = "abcdefghijklmnopqrstuvwxyz"
#---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#main game loop
def main():
while True:
print("\nGenerating word...")
word = list_of_words[random.randint(0, len(list_of_words) - 1)].lower()
word_guess = []
wrong_attempts = 0
wrong_letters = []
game_state = True
for symbol in word:
if symbol in SYMBOL:
word_guess.append("_")
else:
word_guess.append(symbol)
word_show = " ".join(word_guess)
word = list(word)
while game_state != False:
print("\n" + word_show)
print("\nWrong attempts [{0}/5]" .format(wrong_attempts))
if len(wrong_letters) > 0:
print("\nLetters guessed [{0}]" .format(", ".join(wrong_letters)))
letter = "-"
while letter not in SYMBOL or letter == "" or len(letter) > 1:
try:
letter = input("\nGuess a letter or enter 0 to call the ai: ")
except:
print("\nUnexpected error ocurred, try again")
if letter == "0":
correct_letters = [letter for letter in word_guess if letter in SYMBOL]
letter = ai_solver(wrong_letters, word_guess)
elif letter in wrong_letters or letter in word_guess:
print("\nYou already guessed letter [{0}]" .format(letter))
letter = ""
if letter in word:
for i in range(len(word)):
if letter == word[i]:
word_guess[i] = letter
else:
wrong_letters.append(letter)
wrong_attempts += 1
word_show = " ".join(word_guess)
if "".join(word_guess) == "".join(word):
print("\nYou won!")
game_state = False
elif wrong_attempts == 5:
print("\nYou lost!")
print("The word was [{0}]" .format("".join(word)))
game_state = False
option = input("\nWant to play again?[Y/N]: ")
if option.lower().startswith("n"):
sys.exit(0)
def ai_solver(letters_attempted, word_guess):
letters_attempted = letters_attempted if len(letters_attempted) != 0 else ""
available_words = []
for word in list_of_words:
append = False
if len(word) == len(word_guess):
append = True
for i in range(len(word_guess)):
if word[i] in letters_attempted:
append = False
break
if word_guess[i] != "_":
if word[i] != word_guess[i]:
append = False
break
if append == True:
print("[{0}]" .format(word))
available_words.append(word)
common_letters = [letter for letter in "".join(available_words) if letter not in word_guess]
common_letters = Counter("".join(common_letters)).most_common(1)
return common_letters[0][0]
main()
What I tried to do is, to filter all the possible words that have the same length as word_guess.
Then filter out any words that contained a letter that was guessed incorrectly by checking letters_attempted.
Then it would filter out all words that had letters that did not match with word_guess.
if word_guess[i] != "_":
if word[i] != word_guess[i]:
append = False
break
Although it works fine, sometimes it would lose, what can I add to increase the chances of winning?
Thank you!
Your two filter steps are a good first start. There are several different steps you could take to try to improve things. Let's call the words that fit the criteria so far the candidate words.
The first step would be to analyze all the candidate words and figure out which letter appears most frequently in the candidate words. (Not counting repeated letters multiple times.) That letter would make a good next guess.
A slightly more sophisticated approach would look at information gain from a guess. That is, it might be that half the candidate words have a 's', but all such words end in 's'. There might be slight fewer candidate words with a 't', but the 't' can appear anywhere in the word. So, when you guess 't' you actually get a lot more information about what the word could be, because you are shown the location of the 't' when you guess it correctly. Particularly when you don't have enough guesses to figure out every word, such a strategy may help you figure out more words in the guesses that you have.

Saving results of loop iterations in a game

I am trying to make a hangman game and I am running into trouble with the display. I have a loop that is supposed to put the correctly guessed letters in the right places, however it only shows the correct location for one letter at a time. I thought it would be helpful to save the result of the previous iteration, and then display that, but I am not sure how to do that.
import random,time
hanglist = []
answerlist = []
file_var = open("wordlist.100000")
for n in file_var:
hanglist.append(file_var.readline())
word = random.choice(hanglist)
print("word is",word)
guesses = 10
while guesses != 0:
print("guess a letter")
answer = input()
answerlist.append(answer)
if answer in word:
m = list(word)
for n in m:
if n == answer:
print(answer, end = '')
else:
print('_', end = '')
else:
print("close, but not exactly")
guesses -= 1
And here are the outputs
word is fabric
guess a letter
f
f______guess a letter
a
_a_____guess a letter
To solve your issue just replace if n==answer to if n in answer. But, from the above code, I can see code can't handle these issues:
If the user guesses the same word again and again
After 4 guesses are done and total word is guessed, then code should break out of the loop, which it is not happening.
While reading line, it need to strip the '\n' otherwise its really hard
My code addresses these issue:
import random,time
hanglist = []
answerlist = []
file_var = open("wordlist.100000")
for n in file_var:
# strips the '/n' at the end
hanglist.append(file_var.readline().rstrip())
word = random.choice(hanglist)
print("word is",word)
guesses = 10
while guesses!=0:
print("guess a letter")
answer = input()
if answer in answerlist:
continue
answerlist.append(answer)
if answer in word:
# to print entire word guessed till now- with current and previous iterations
word_print = ''
for n in word:
# to print all the last state occurences
if n in answerlist:
word_print += n
else:
word_print += '_'
print(word_print,end='')
# word is correctly guessed
if '_' not in word_print:
break
else:
print("close, but not exactly")
guesses = guesses-1
Your issue is with
if n == answer:
print(answer,end = '')
else:
print('_', end = '')
which only compares each letter with the current guess, answer. Instead, if you use
if n in answerlist:
print(n, end = '')
else:
print('_', end = '')
it will show the letter if that letter is in the list of their previous guesses.
Additionally: the previous m= list(word) is not necessary, as for n in word: is valid.

how to check repeating Vowels

I'm pretty new to python and I'm having trouble with my
if then else statements and I only get is "no repeating vowels" which mean my rep_vowel is still returning 0
so the program rules are as follows.
if no vowel appears next to itself (e.g. hello), then print:
no vowel repeats
if exactly one vowel is repeated in sequence at least once (e.g. committee) then print a message that indicates which vowel repeats:
only vowel e repeats
if more than one vowel repeats (e.g. green door) then print:
more than one vowel repeats
ignore upper case - lower case differences: assume all the input is always lowercase
answer = input("Enter a string: ")
rep_vowel = 0
i = 0
length_Answer = len(answer)
next_string = 1
curChar = answer[0+rep_vowel]
for i in range(0,length_Answer):
if answer[0 + i] in ["a","e","i","o","u"]:
i =+ 1
next_string = answer[0+i+i]
if next_string == answer:
rep_vowel =+ 1
if rep_vowel == 0:
print("no repeating vowles")
elif rep_vowel > 1:
print("more than 1 repeating vowels")
else:
print ("the letter "+ str(curChar) +" repeats")
You have a few mistakes so i'll try to address several of them:
You do a lot of [0 + something] indexing, which is useless, since 0 + something always equals to something, so yo should just do indexing with [something]
Changing the value of i with i += 1 is bad because you are already increasing it as part of the loop
All you have to do to find a match is simply match the current letter to the next one, if both are the same and they are also vowels, you've found a match.
You are initializing unnecessary variables such as i = 0 only to have them overridden in the next lines
Adding all of those together:
answer = input("Enter a string: ")
vowels = "aeiou"
repeats = [] # this list will hold all repeats of vowels
for i in range(len(answer) - 1): # i'll explain the -1 part at the end
if answer[i] in vowels and answer[i] == answer[i + 1]:
repeats.append(answer[i])
if len(repeats) == 0:
print("no repeating vowles")
elif len(repeats) > 1:
print("more than 1 repeating vowels")
else:
print("the letter " + repeats[0] + " repeats")
This still doesn't take every possible input into account, but it should get you started on a final solution (or perhaps that's enough). For example, input of teest will give the correct result but the input of teeest doesn't (depends on your definition of correct).
About the len(answer-1) range, that's only to make sure we don't go out of bounds when doing answer[i + 1], so we're stopping on the next to last letter instead.
Firstly, you have to indent your code.
to say if (condition) then do print('hello') you write it this way:
if condition:
print('hello')
Secondly, you are using i =+ 1 which is the same as i=1
I think you meant i +=1 which is i = i+1
Finally, I suggest this code:
answer = input("Enter a string: ")
vowel_repeated_count = 0
length_Answer = len(answer)
i=0
while (i <length_Answer-1):
#we check if it's a vowel
if answer[i] in ["a","e","i","o","u"]:
#we check if it's followed by the same vowel
if answer[i+1] == answer[i]:
#increment the vowel_repeated_count
vowel_repeated_count +=1
#we save the vowel for the display
vowel = answer[i]
#we skip the other same repeated vowels
#example: abceeed, we skip the third e
while (answer[i] == vowel and i < length_Answer-1):
i +=1
#we add this incrementation because we're in a while loop
i +=1
if vowel_repeated_count == 0:
print("no repeating vowles")
elif vowel_repeated_count == 1:
print("the letter "+ str(vowel) +" repeats")
else:
print ("more than 1 repeating vowels")
You have some logical errors. It's time consuming to edit that. You can try this, I have modified your code. Hope it will work for you. I have commented beside every important line.
answer = input("Enter a string: ")
is_found = {} #a dictionary that will hold information about how many times a vowel found,initially all are 0
is_found["a"]=0
is_found["e"] = 0
is_found['i']=0
is_found['o']=0
is_found['u']=0
vowels =["a","e","i","o","u"]
for i in range(0,len(answer)):
if answer[i] in vowels:
is_found[answer[i]] = is_found[answer[i]]+1 # if a vowel found then increase its counter
repeated=0 #let 0 repeated vowel
previously_repeated=False #to trace whether there is a previously repeated character found
curChar=None
for key,value in is_found.items(): #iterate over dictionary
if previously_repeated and value>1: #if a vowel found and previously we have another repeated vowel.
repeated=2
elif previously_repeated==False and value>1: # we don't have previously repeated vowel but current vowel is repeated
curChar=key
previously_repeated=True
repeated=1
if repeated== 0:
print("no repeating vowles")
elif repeated> 1:
print("more than 1 repeating vowels")
else:
print ("the letter "+ str(curChar) +" repeats")
There is no need to increment your counter i. In your for loop, it will increment itself each time it goes through the for loop. Also, you need a variable to keep track of how many times the vowel repeats.
answer = input("Enter a string: ")
rep_vowel = 0
length_Answer = len(answer)
vowelList=["a","e","i","o","u"]
vowelRepeated = []
#this will go from i=0 to length_Answer-1
for i in range(length_Answer):
if (answer[i] in vowelList) and (answer[i+1] in vowelList):
if (answer[i] == answer[i+1]):
vowelRepeated.append(answer[i])
repVowel += 1
if rep_vowel==0:
print("no repeating vowels")
elif rep_vowel==1:
print("only one vowel repeated:")
print(vowelRepeated)
else:
print("multiple vowels repeated:")
print(vowelRepeated)
for such counting, I will prefer to use a dictionary to keep the counting number. Your code has been modified for your reference
answer = input("Enter a string: ")
length_Answer = len(answer)
count = dict()
for i in range(length_Answer):
if answer[i] in ["a","e","i","o","u"]:
if answer[i+1] == answer[i]:
if answer[i] in count:
count[answer[i]] += 1
else:
count[answer[i]] = 1
rep_vowel = len(count)
if rep_vowel == 0:
print("no repeating vowles")
elif rep_vowel > 1:
print("more than 1 repeating vowels")
else:
for k in count:
vowel = k
print("the letter " + vowel + " repeats")
You have a few issues with your solution :
1) You never use curChar, i'm guessing you wanted to enter the next_string value into it after the '==' statement.
2) You compare your next_string to answer, this will always be a false statement.
3) Also no need to use [0+i], [i] is good enough
Basically what you want to do is this flow :
1) Read current char
2) Compare to next char
3) If equal put into a different variable
4) If happens again raise a flag
Optional solution :
vowel_list = ["a","e","i","o","u"]
recuring_vowel_boolean_list = [answer[index]==answer[index+1] and answer[index] in vowel_list for index in range(len(answer)-1)]
if not any(recuring_vowel_boolean_list ):
print("no repeating vowels")
elif (recuring_vowel_boolean_list.count(True) > 1):
print("More then 1 repeating vowels")
else:
print("The letter {} repeats".format(answer[recuring_vowel_boolean_list.index(True)]))

Can't Break Out of While Loop

I wrote the following python code. It takes a list of English words I found on the internet and makes them a list so that I can use them for hangman. Well my problem is that every time I run this program and successfully guess the word, it doesn't break out of the while loop. It just keeps going. I can't figure out why for the life of me. Anyone have any clue as to why it isn't printing the final message to the winner?
import random
words = []
lettersGuessed = []
isGuessed = 0
wordFile = open(r'C:\Users\Sarah\PycharmProjects\hangman\words.txt')
for word in wordFile:
words.append(word.rstrip(wordFile.readline()))
mysteryWord = random.choice(words)
while len(mysteryWord) <= 1:
mysteryWord = random.choice(words)
for letter in mysteryWord:
print("?", end = "")
print("\n")
def isWon():
#win conditions
count = 0
for letter in mysteryWord:
if letter in lettersGuessed:
count += 1
if count == len(mysteryWord):
isGuessed = 1
count = 0
while isGuessed == 0:
guess = input("Guess a letter \n")
if guess.upper() or guess.lower() in mysteryWord:
lettersGuessed.append(guess)
for letter in mysteryWord:
if letter in lettersGuessed:
print(letter, end ='')
else:
print("?", end = '')
print("\n")
count = 0
isWon()
if isGuessed == 1:
break
print("Congratulations, you correctly guessed ", mysteryWord)
isGuessed in your top-level code and isGuessed in isWon function are two different variables. A function is a separate namespace (else a function using a variable with common name like i would wreak havoc in other code).
This can be solved by a global declaration, but it's a very bad style. Same applies to variables like mysteryWord and lettersGuessed.
Instead, you should return the value from the isWon function:
def isWon(mysteryWord, lettersGuessed):
# do your counting...
return isGuessed
# main code
victory = False
while not victory:
# ...
victory = isWon(mysteryWord, lettersGuessed)
# you don't even need the if ... break statement
BTW your check for all letters being guessed can be made a one-liner:
def isWon(mysteryWord, lettersGuessed):
return set(lettersGuessed) == set(mysteryWord)
The immediate issue is that isWon() is not setting isGuessed regardless of the input. If you guess with the string "foo" then
lettersGuessed.append(guess)
will make lettersGuessed a list with one item, which is a string. I think what you were trying to do was
lettersGuessed.extend(list(guess))
Which will add each letter in guess to the lettersGuessed list.
Two points also worth mentioning:
isWon() will consider the game won if you guess an anagram of the word in in questions e.g. "oof" will be considered a correct solution if the word is "foo"
words.append(word.rstrip(wordFile.readline())) is reading every even line of the input file, and adding it to the words list after removing any characters it has in common with the following word. You want to do words.append(word.strip()) instead.
It's all about scope. isGuessed used in isWon() is define in the local scope. If you want to affect isGuessed declared in the global scope you will have to either pass it to isWon() as a parameter or use the global keyword before modifying isGuessed. See below:
def isWon():
#win conditions
count = 0
for letter in mysteryWord:
if letter in lettersGuessed:
count += 1
if count == len(mysteryWord):
global isGuessed
isGuessed = 1
Output with this change:
python3 test.py
?????
Guess a letter
1
?????
Guess a letter
2
?????
Guess a letter
3
????3
Guess a letter
4t
????3
Guess a letter
t
t??t3
Guess a letter
e
te?t3
Guess a letter
s
test3
Congratulations, you correctly guessed test3
You're trying to communicate using the global variable is_guessed, but the isWon function doesn't gave a global is_guessed line, so it is setting a variable local to isWon named is_guessed rather than the global variable.
My suggestion would be, rather than adding global is_guessed to isWon(), to return either True or False from isWon() (based on whether or not the user has won) and use that to end the loop.
Here is an alternative version of your code:
import random
words = []
with open(r'C:\Users\Sarah\PycharmProjects\hangman\words.txt') as wordFile:
for word in wordFile: # assuming one word per line
words.append(word.strip()) # iterating a file reads one line per iteration
mysteryWord = random.choice(words)
mysteryLetters = set(mysteryWord.lower())
lettersGuessed = set()
def isWon():
return mysteryLetters == (lettersGuessed & mysteryLetters)
while not isWon():
for letter in mysteryWord:
if letter in lettersGuessed:
print(letter, end ='')
else:
print("?", end = '')
print()
guess = input("Guess a letter \n")[:1].lower()
if guess in mysteryWord:
lettersGuessed.add(guess)
print("Congratulations, you correctly guessed ", mysteryWord)
Well, I know that my answer is a little late but here's my solution:
#!/usr/bin/env python3
import random
word_file_name = "/usr/share/dict/canadian-english"
with open(word_file_name) as word_file:
# I'm assuming your input file has one word per line and that
# you want to keep only words that has more than one letter
words = [word.rstrip() for word in word_file if len(word) > 1]
mystery_word = random.choice(words)
# Using sets helps to remove duplicate letters and eases membership tests
letters_mystery = set(mystery_word.upper())
letters_guessed = set()
not_guessed = True
while not_guessed:
# We create a list with all the letters found or not
letters_to_show = [letter if letter.upper() in letters_guessed else "?"
for letter in mystery_word]
# We join them before printing them
print("".join(letters_to_show), "\n")
guess_received = input("Guess a letter :")
if guess_received.strip():
# We only keep the first letter received
guess_kept = guess_received[0].upper()
if guess_kept in letters_mystery:
letters_guessed.add(guess_kept)
# We determine if we need to continue
not_guessed = letters_guessed != letters_mystery
print("Congratulations, you correctly guessed", mystery_word)
Key points:
A list comprehension is used to put the words in a list
Sets are used to keep a group of letters without duplicates.
A conditional expression is used to choose if a letter will be shown or or a ?
Truth testing can be used to simplify the verification of certain information
You are using expressions like isGuessed == 1 like in C where True equals 1 and False equals 0. In Python, a variable can be a boolean. You can use it directly in a if statement

Categories