Odd Python logic error - python

I apologize if this is just a dumb slip-up on my part, but I am relatively inexperienced with Python and I can't figure out why this isn't working.
I have a class called Game, which contains a word_list that has been read in from a text file. One of the method of the class is as follows:
def make_guess(self, guess):
print("Guess: ", guess)
if guess == self.target_word:
print("Got it!")
if guess in self.word_list:
num_right = self.compare_letters(guess, self.target_word)
else:
print("Not valid guess; not in list")
No matter what input I give it, I can never make it trip the if guess in self.word_list path. I tried comparing the type of the variables (each word in the list, and my input), but they appeared to be the same to me.
The whole definition of the class if it helps:
class Game:
def __init__(self, difficulty):
self.difficulty = difficulty
if 0 < difficulty < 3:
self.remaining_guesses = 5
elif 3 <= difficulty < 5:
self.remaining_guesses = 4
else:
self.remaining_guesses = 3
self.word_list = []
self.dictionary = open("wordsEn.txt")
for word in self.dictionary:
percent = int(floor(1000*random()))
if len(word) == 6 and percent < 2:
self.word_list.append(word)
self.dictionary.close()
percent = int(floor(len(self.word_list)*random()))
self.target_word = self.word_list[percent]
def make_guess(self, guess):
print("Guess: ", guess)
if guess == self.target_word:
print("Got it!")
if guess in self.word_list:
num_right = self.compare_letters(guess, self.target_word)
else:
print("Not valid guess; not in list")
def display_word_list(self):
print("in display")
print(self.remaining_guesses)
for word in self.word_list:
print(word)
print("Target: ", self.target_word)
def compare_letters(self, guess, target_word):
for letter in guess:
if letter == letter:
print("yes")
`
In main, I have:
new_game = Game(difficulty)
guess = input("Guess: ")
new_game.make_guess(guess)
Even if I deliberately guess a word that I know to be in the list, it never says that the word is in fact in the list. What stupid mistake am I making? (and if you could point out ways I could adhere more to the Python style, that would be appreciated as well!)

You need to strip newlines from lines of wordsEn.txt. After
for word in self.dictionary:
insert:
word = word.rstrip()
I'm assuming that each line of wordsEn.txt lists a single word.

Instead of adding the full line to self.word_list, add each word by calling self.dictionary = open("wordsEn.txt").read().split() instead. Here is your edited class:
class Game:
def __init__(self, difficulty):
self.difficulty = difficulty
if 0 < difficulty < 3:
self.remaining_guesses = 5
elif 3 <= difficulty < 5:
self.remaining_guesses = 4
else:
self.remaining_guesses = 3
self.word_list = []
self.dictionary = open("wordsEn.txt").read().split()
for word in self.dictionary:
percent = int(floor(1000*random()))
if len(word) == 6 and percent < 2:
self.word_list.append(word)
self.dictionary.close()
percent = int(floor(len(self.word_list)*random()))
self.target_word = self.word_list[percent]
def make_guess(self, guess):
print("Guess: ", guess)
if guess == self.target_word:
print("Got it!")
if guess in self.word_list:
num_right = self.compare_letters(guess, self.target_word)
else:
print("Not valid guess; not in list")
def display_word_list(self):
print("in display")
print(self.remaining_guesses)
for word in self.word_list:
print(word)
print("Target: ", self.target_word)
def compare_letters(self, guess, target_word):
for letter in guess:
if letter == letter:
print("yes")
Demonstrating the above concept of .read().split():
>>> file = open('blah.txt')
>>> for word in file:
... word
...
'Hello,\n'
'\n'
'These\n'
'Are\n'
'Some\n'
'Vocabulary\n'
'Words\n'
'\n'
'Regards,\n'
'Me\n'
>>> file = open('blah.txt').read().split()
>>> for word in file:
... word
...
'Hello,'
'These'
'Are'
'Some'
'Vocabulary'
'Words'
'Regards,'
'Me'
>>>

In the line where you say
for word in self.dictionary:
This reads an entire line from the text file. So the variable word doesn't refer to a word in the text file. You should first read a line from the text file and then take individual words from the line. Like this :
for line in self.dictionary:
words=line.split();
for word in words:

Related

solving positional argument error in python

I am attempting to write a program in python that simulates a game of cheating hangman, but am receiving positional argument errors upon compilation. I wrote the class and methods in hangman.py and called the play method in play_hangman.py. When I attempt to run it, it gives the following error:
play() missing 9 required positional arguments: 'askForWordLength', 'askForNumberOfGuesses', 'remainingWords', 'words', 'wordStatus', 'printCountOfRemainingWords', 'printGameStats', 'askPlayerForGuess', and 'retrieveRemainingWords'
play_hangman.py
from hangman import Hangman
game = Hangman()
game.play()
y = input("Would you like to play again? yes or no: ")
while y == 'yes':
game.play()
y = input("Would you like to play again? yes or no: ")
hangman.py
import re
class Hangman:
# hangman self method
def hangman(self):
self.hangman = Hangman() # object of the Hangman class
def words(self):
with open('dictionary.txt') as file: # opens dictionary text file
file_lines = file.read().splitlines() # reads and splits each line
all_words = [] # empty list to contain all words
valid_words = [] # empty list to contain all valid words
for word in file_lines: # traverses all words in the file lines
if len(word) >= 3: # accepts word if it has at least 3 letters
all_words.append(word) # appends accepted word to list
# list of all invalid characters in python
CHARACTERS = ["~", "`", "!", "#", "#", "$", "%", "^", "&", "*", "(",
")", "-", "_", "=", "+", "[", "]", "{", "}", "|", "\","
"", "'", "?", "/", ">", ".", "<", ",", "", ";", ":"]
for i in CHARACTERS: # traverse list of invalids
for word in all_words:
if i not in word: # if invalid character is not in word
valid_words.append(word) # accept and append to list
return valid_words # return list of valid words
def askForWordLength(self, valid_words):
word_lengths = [] # empty list for possible word lengths
for word in valid_words: # traverse list of valid words
length = word.__len__() # record length of current word
if (length not in word_lengths):
word_lengths.append(length) # accept and append to list
word_lengths.sort()
# inform user of possible word lengths
print('The available word lengths are: ' + str(word_lengths[0]) + '-'
+ str(word_lengths[-1]))
print()
# have user choose from possible word lengths
while(1):
try:
length = int(input('Please enter the word length you want: '))
if (length in word_lengths):
return length
except ValueError:
print('Your input is invalid!. Please use a valid input!')
print()
def askForNumberOfGuesses(self):
while(1):
try:
num_guesses = int(input('Enter number of guesses you want: '))
if (num_guesses >= 3):
return num_guesses
except ValueError:
print('Your input is invalid!. Please use a valid input!')
print()
def wordStatus(self, length):
status = '-'
for i in range(0, length):
status += '-'
return
def remainingWords(self, file_lines, length):
words = []
for word in file_lines:
if (word.__len__() == length):
words.append(word)
return words
def printGameStats(self, letters_guessed, status, num_guesses):
print('Game Status: ' + str(status))
print()
print('Attempted Guesses' + str(letters_guessed))
print('Remaining Guesses' + str(num_guesses))
def askPlayerForGuess(self, letters_guessed):
letter = str(input('Guess a letter: ')).lower()
pattern = re.compile("^[a-z]{1}$")
invalid_guess = letter in letters_guessed or re.match(pattern, letter) == None
if (invalid_guess):
while (1):
print()
if (re.match(pattern, letter) == None):
print('Invalid guess. Please enter a correct character!')
if (letter in letters_guessed):
print('\nYou already guessed that letter' + letter)
letter = str(input('Please guess a letter: '))
valid_guess = letter not in letters_guessed and re.match(pattern, letter) != None
if (valid_guess):
return letter
return letter
def retrieveWordStatus(self, word_family, letters_already_guessed):
status = ''
for letter in word_family:
if (letter in letters_already_guessed):
status += letter
else:
status += '-'
return status
def retrieveRemainingWords(self, guess, num_guesses, remaining_words,
wordStatus, guesses_num, word_length,
createWordFamiliesDict,
findHighestCountWordFamily,
generateListOfWords):
word_families = createWordFamiliesDict(remaining_words, guess)
family_return = wordStatus(word_length)
avoid_guess = num_guesses == 0 and family_return in word_families
if (avoid_guess):
family_return = wordStatus(word_length)
else:
family_return = findHighestCountWordFamily(word_families)
words = generateListOfWords(remaining_words, guess, family_return)
return words
def createWordFamiliesDict(self, remainingWords, guess):
wordFamilies = dict()
for word in remainingWords:
status = ''
for letter in word:
if (letter == guess):
status += guess
else:
status += '-'
if (status not in wordFamilies):
wordFamilies[status] = 1
else:
wordFamilies[status] = wordFamilies[status] + 1
return wordFamilies
def generateListOfWords(self, remainingWords, guess, familyToReturn):
words = []
for word in remainingWords:
word_family = ''
for letter in word:
if (letter == guess):
word_family += guess
else:
word_family += '-'
if (word_family == familyToReturn):
words.append(word)
return words
def findHighestCountWordFamily(self, wordFamilies):
familyToReturn = ''
maxCount = 0
for word_family in wordFamilies:
if wordFamilies[word_family] > maxCount:
maxCount = wordFamilies[word_family]
familyToReturn = word_family
return familyToReturn
def printCountOfRemainingWords(self, remainingWords):
show_remain_words = str(input('Want to view the remaining words?: '))
if (show_remain_words == 'yes'):
print('Remaining words: ' + str(len(remainingWords)))
else:
print()
def play(self, askForWordLength, askForNumberOfGuesses, remainingWords,
words, wordStatus, printCountOfRemainingWords, printGameStats,
askPlayerForGuess, retrieveRemainingWords):
MODE = 1
openSession = 1
while (openSession == 1):
word_length = askForWordLength(words)
num_guesses = askForNumberOfGuesses()
wordStatus = wordStatus(word_length)
letters_already_guessed = []
print()
game_over = 0
while (game_over == 0):
if (MODE == 1):
printCountOfRemainingWords(remainingWords)
printGameStats(remainingWords, letters_already_guessed,
num_guesses, wordStatus)
guess = askPlayerForGuess(letters_already_guessed)
letters_already_guessed.append(guess)
num_guesses -= 1
remainingWords = retrieveRemainingWords(guess, remainingWords,
num_guesses, word_length)
wordStatus = wordStatus(remainingWords[0], letters_already_guessed)
print()
if (guess in wordStatus):
num_guesses += 1
if ('-' not in wordStatus):
game_over = 1
print('Congratulations! You won!')
print('Your word was: ' + wordStatus)
if (num_guesses == 0 and game_over == 0):
game_over = 1
print('Haha! You Lose')
print('Your word was: ' + remainingWords[0])
print('Thanks for playing Hangman!')```
Your play() method requires many arguments:
def play(
self,
askForWordLength,
askForNumberOfGuesses,
remainingWords,
words,
wordStatus,
printCountOfRemainingWords,
printGameStats,
askPlayerForGuess,
retrieveRemainingWords
):
...
When you call the function, you need to provide all of those arguments, aside from self, otherwise, Python won't know what the value of those variables should be.

Python - Every other letter in a string capitalized within a loop where the data was handed down from a copied list of user input

I was instructed to have a user input at least 8 words into a list and then perform various manipulations to the data within the list. One of the manipulations it asks me to do is to create a loop that makes every other letter in the strings capitalized (hElLo WoRlD.) For better readability, I left out the other manipulations that I have done to the code.
import sys
def main():
words = []
wordCount = 0
userWord = input("Enter at least 8 words or 'bye' to leave the program: ").split(' ')
while True:
if len(userWord)<8:
print("Please print at least 8 words, try again.")
sys.exit()
elif wordCount >= 8 and userWord[wordCount] != 'bye':
words.append(userWord[wordCount])
wordCount = wordCount + 1
else:
break
every_other (userWord)
def every_other(words):
words6 = words.copy()
st = ""
for i in range(len(words6)):
if (i%2) == 0:
st += words6[i].upper()
else:
st += words6[i]
print ('This is your list with every other letter capitalized: ', words6)
return st
main()
I am not getting any error messages but the code doesn't seem to be running starting at def every_other.
You'll have to print the function every_other as it returns a string:
import sys
def main():
words = []
wordCount = 0
userWord = input("Enter at least 8 words or 'bye' to leave the program: ").split(' ')
while True:
if len(userWord)<8:
print("Please print at least 8 words, try again.")
sys.exit()
elif wordCount >= 8 and userWord[wordCount] != 'bye':
words.append(userWord[wordCount])
wordCount = wordCount + 1
else:
break
print('This is your list with every other letter capitalized: ', every_other(userWord))
def every_other(words):
words6 = words.copy()
st = ""
for i in range(len(words6)):
if (i%2) == 0:
st += words6[i].upper()
else:
st += words6[i]
return st
#print ('This is your list with every other letter capitalized: ', words6) # This will never run as the function has already returned
main()
If you want to capitalize every second character:
import sys
def main():
words = []
wordCount = 0
userWord = input("Enter at least 8 words or 'bye' to leave the program: ").split(' ')
while True:
if len(userWord)<8:
print("Please print at least 8 words, try again.")
sys.exit()
elif wordCount >= 8 and userWord[wordCount] != 'bye':
words.append(userWord[wordCount])
wordCount = wordCount + 1
else:
break
print('This is your list with every other letter capitalized: ', every_other(userWord))
def every_other(words):
st = ""
new_st = ""
for w in words:
st+=w
print(str(st))
for count, val in enumerate(st):
if (count % 2) == 0:
val = val.upper()
new_st+=val
return new_st
main()

Inheritance answer overlap

I have to make a program that converts a string to pig latin and include an constructor + example of the program. I then have to make a subclass based on it with a overwritten method to add a few new rules.
In the original class file I have the constructor:
pig = pigLatin_Class("First test")
print(pig)
pig.sentence = "Changing it up"
print(pig)
Which works correctly, however in my new subclass:
gib = gibberish_class("test")
print(gib)
Which also works correctly but prints out the answers from the super class as well, even though they're outside of the class definition.
I'm using:
import assignment_a3_1 as a3_1
class gibberish_class(a3_1.pigLatin_Class):
as my inheritance.
Any solutions?
EDIT:
In regards to the naming conventions, I'm just using what we were told to use, also I've only been coding for a month or two at most, doing a uni course, be gentle! :D
Super:
class pigLatin_Class(object):
vowels = ["a","e","i","o","u","A","E","I","O","U"]
def __init__(self, initialSentence):
self.__sentence = initialSentence
self.sentencePig = []
self.pLatin_converter(self.__sentence)
def pLatin_converter(self, sentence):
wordList = sentence.split(" ")
for word in wordList:
isVowel = False
wList = list(word)
for character in word: #vowel checks
if(character in pigLatin_Class.vowels):
isVowel = True
break
if(isVowel == False): #finishing if no vowels
wList.append(wList.pop(0))
word = ''.join(wList) + "way "
self.sentencePig.append(word)
if(''.join(wList) == word): #Stops it from iterating through again if it contains no vowels
if(wList[0] in pigLatin_Class.vowels):
word = ''.join(wList) + "hay "
self.sentencePig.append(word)
elif(wList[0] not in pigLatin_Class.vowels): #contains vowels but not first
for i in range(len(wList)):
if(wList[i] in pigLatin_Class.vowels):
wList = wList[i:] + wList[:i]
word = ''.join(wList) + "ay "
self.sentencePig.append(word)
break
def __str__(self):
string = ("\n The translation of '" + self.__sentence + "' is: " + ''.join(self.sentencePig))
return string
#property
def sentence(self):
return self.__sentence
#sentence.setter
def sentence(self, value):
self.__sentence = value
self.sentencePig = []
self.pLatin_converter(self.__sentence)
pig = pigLatin_Class("First test")
print(pig)
pig.sentence = "Changing it up"
print(pig)
Subclass:
import assignment_a3_1 as a3_1
class gibberish_class(a3_1.pigLatin_Class):
symb = ["0","1","2","3","4","5","6","7","8","9",",",".","/",";","#","[","]","=","-","(",")","*","&","^","%","$","£","_","+","{","}","~","<","#",":","?",">","<","|"]
vowels = a3_1.pigLatin_Class.vowels
def pLatin_converter(self, sentence):
wordList = sentence.split(" ")
for word in wordList:
suffix = 0
isVowel = False
wList = list(word)
for character in word: #vowel checks
if(character in gibberish_class.vowels):
isVowel = True
break
if(isVowel == False): #finishing if no vowels
wList.append(wList.pop(0))
suffix = 1
if(''.join(wList) == word): #Stops it from iterating through again if it contains no vowels
if(wList[0] in gibberish_class.vowels):
suffix = 2
elif(wList[0] not in gibberish_class.vowels): #contains vowels but not first
for i in range(len(wList)):
if(wList[i] in gibberish_class.vowels):
wList = wList[i:] + wList[:i]
suffix = 3
break
for character in wList:
#print(character)
if(character in gibberish_class.symb):
wList.append(character)
if(suffix == 1):
word = ''.join(wList) + "way "
elif(suffix == 2):
word = ''.join(wList) + "hay "
elif(suffix == 3):
word = ''.join(wList) + "ay "
self.sentencePig.append(word)
gib = gibberish_class("test")
gib.pLatin_converter
print(gib)
EDIT TWO:
The another question was very helpful in stopping the main method, however the str method is still called in the first question, just printing an empty string, said if statement just causes the program to throw errors if used in the str method. How would I solve that?
Here's a skeleton of how a typical program like yours could look.
class PigLatin(object):
def __init__(self, text):
...
# Add helper methods to taste.
def splitIntoWords(self):
return ... # re.split would help here.
def mangle(self):
# Do your conversion, put it into result
...
return result
class Gibberish(PigLatin):
# No __init__ since you inherit it.
def mangle(self):
# This method replaces, aka overrides, mangle() of PigLatin.
# You can use other methods, e.g. self.splitIntoWords().
...
return result
if __name__ == '__main__':
text = 'Hello world!'
print 'Do you know what "%s" would be in Pig Latin?' % text
print 'It is %s' % PigLatin(text).mangle()
print 'And now some Gibberish: %s' Gibberish(text).mangle
Hope this helps.

CodeHS Python, remove all from string

I am using CodeHS for my Computer Science Principles class and one of the problems in the Strings section is really confusing me. We have to remove all of one string from another string.
These are the official instructions:
Write a function called remove_all_from_string that takes two strings, and returns a copy of the first string with all instances of the second string removed. You can assume that the second string is only one letter, like "a".
We are required use:
A function definition with parameters
A while loop
The find method
Slicing and the + operator
A return statement
We are expected to only have to use those 5 things to make it work.
I attempted to write this program but my function doesn't do anything and I am really stumped.
def remove_all_from_string(word, letter):
while letter in word:
x=word.find(letter)
if x==-1:
continue
else:
return x
print word[:x] + word[x+1:]
remove_all_from_string("alabama", "a")
The easiest way to do this would obviously just be
def remove_all_from_string(word, letter):
return word.replace(letter, "")
However, considering the parameters, another way we could do this is like so:
def remove_all_from_string(word, letter):
while letter in word:
x=word.find(letter)
if x == -1:
continue
else:
word = word[:x] + word[x+1:]
return word
You could run this and print it by typing
>>> print(remove_all_from_string("Word Here", "e"))
#returns Word hr
def remove_all_from_string(word, letter):
while letter in word:
x=word.find(letter)
if x == -1:
continue
else:
word = word[:x] + word[x+1:]
return word
print(remove_all_from_string("hello", "l"))
def remove_all_from_string(word, letter):
letters = len(word)
while letters >= 0:
x=word.find(letter)
if x == -1:
letters = letters - 1
continue
else:
# Found a match
word = word[:x] + word[x+1:]
letters = letters - 1
return word
remove_all_from_string("alabama", "a")
I have this so far and it keeps saying that message is not defined and when I define it with find_secret_word it says "find_secret_word" is not defined, what do I do?
This is my code:
`word = "bananas"
letter = "na"
index = word.find(letter)
def remove_all_from_string(word, letter):
while letter in word:
x=word.find(letter)
if x == -1:
continue
else:
word = word[:x] + word[x+1:]
return word
word = word[:index] + word[index+len(letter):]
print(remove_all_from_string("hello", "l"))
def find_secret_word(message):
while True:
return hidden_word
hidden_word = "iCjnyAyT"
for letter in message:
if letter.upper():
hidden_word = hidden_word + letter
print (find_secret_word(message))`

Hangman on python: How do I make it if I input a letter more than once, it will be considered in correct?

So I'm doing hangman on python, and I was wondering how I would mark a letter incorrect if it has already been used.
def __init__(self):
self.wordLetter = []
self.binaryWord = []
self.wordLength = 0
self.numberCorrect = 0
self.numberIncorrect = 0
def secretWord(self):
self.numberCorrect = 0
self.numberIncorrect = 0
self.wordLetters = ['f','o','o','t','b','a','l','l']
self.wordLength = len(self.letterWord)
for val in range(0,self.wordLength):
self.binaryWord.append(0)
def checkLetter(self, letter):
for val in range(len(self.wordLetter)): #checks if letter is correct and takes appropriate action
if self.wordLetter[val] == letter:
self.binaryWord[val] = 1
self.numberCorrect += 1
print "CORRECT!!"
if letter not in self.wordLetters:
self.numberIncorrect += 1
print "Incorrect letter. Try again"
If the word is "football," how would I make it so if I input the letters f,o,t,b,a, or l more than once, it will come up as incorrect?
keep track of the letters the user has already submitted
def __init__(self):
...
...
self.submittedLetters[]
...
...
Then in your check letter check and see if the letter is already in the list of letters
if letter in self.submittedLetters:
#already entered
else:
#add letter to self.submittedLetters
...
#the rest of your method
You can save in one variable word and in another a set of this word
self.word = 'football'
self.wordLatters = set(self.word)
And check letter like this
def checkLetter(self, letter):
if letter in self.wordLatters:
self.binaryWord[val] = 1
self.numberCorrect += 1
self.wordLatters.remove(letter)
print "CORRECT!!"
else:
self.numberIncorrect += 1
print "Incorrect letter. Try again"

Categories

Resources