I am trying to expand on Codeacademy's Pig Latin converter to practice basic programming concepts.
I believe I have the logic nearly right (I'm sure it's not as concise as it could be!) and now I am trying to output the converted Pig Latin sentence entered by the user on a single line.
If I print from inside the for loop it prints on new lines each time. If I print from outside it only prints the first word as it is not iterating through all the words.
Could you please advise where I am going wrong?
Many, many thanks for your help.
pyg = 'ay'
print ("Welcome to Matt's Pig Latin Converter!")
def convert(original):
while True:
if len(original) > 0 and (original.isalpha() or " " in original):
print "You entered \"%s\"." % original
split_list = original.split()
for word in split_list:
first = word[0]
new_sentence = word[1:] + first + pyg
final_sentence = "".join(new_sentence)
print final_sentence
break
else:
print ("That's not a valid input. Please try again.")
return convert(raw_input("Please enter a word: "))
convert(raw_input("Please enter a word: "))
Try:
pyg = 'ay'
print ("Welcome to Matt's Pig Latin Converter!")
def convert(original):
while True:
if len(original) > 0 and (original.isalpha() or " " in original):
final_sentence = ""
print "You entered \"%s\"." % original
split_list = original.split()
for word in split_list:
first = word[0]
new_sentence = word[1:] + first + pyg
final_sentence = final_sentence.append(new_sentence)
print final_sentence
break
else:
print ("That's not a valid input. Please try again.")
return convert(raw_input("Please enter a word: "))
convert(raw_input("Please enter a word: "))
It's because you are remaking final_sentence every time in the for loop instead of adding to it.
I'm not sure of the program logic but a quick solution would be appending all the final_sentence in a list, and after the for print the list with a Join.
pyg = 'ay'
print ("Welcome to Matt's Pig Latin Converter!")
def convert(original):
to_print = []
while True:
if len(original) > 0 and (original.isalpha() or " " in original):
print "You entered \"%s\"." % original
split_list = original.split()
for word in split_list:
first = word[0]
new_sentence = word[1:] + first + pyg
final_sentence = "".join(new_sentence)
to_print.append(final_sentence)
print " ".join(to_print)
break
else:
print ("That's not a valid input. Please try again.")
return convert(raw_input("Please enter a word: "))
convert(raw_input("Please enter a word: "))
This code does what you want?
Your issue is here:
for word in split_list:
first = word[0]
new_sentence = word[1:] + first + pyg
final_sentence = "".join(new_sentence)
print final_sentence
You are joining a single word to itself. You will want to save all the words from inside the loop, then print them once the loop are processed them all.
final = []
for word in split_list:
new_word = word[1:] + word[0] + pyg
final.append(new_word)
print ' '.join(final)
Or, just for fun, here's the one-liner:
print ' '.join([word[1:]+word[0]+'ay' for word in split_list])
EDIT: Also, #furas makes a good point in their comment, to print with no newline simply add a , to the end of the print statement:
for word in split_list:
first = word[0]
print word[1:] + first + pyg,
Related
I am trying to create a program that asks for a word input until '' is entered. Then the program will print out all of the words joined in a sentence. Then take the first letter of each word to make an acrostic. I am using python. Example shown below. Thank you in advance. This is due really soon. :)
What I have coded:
sentence = []
acrostic = []
word = -1
while word:
sentence.append(word)
acrostic.append(sentence[0].upper())
print(sentence)
print("-- {}".format(acrostic))
What I want the code to do:
Word: A
Word: cross
Word: tick
Word: is
Word: very
Word: evil
Word:
A cross tick is very evil
-- ACTIVE
For input:
in a loop, ask the user a word, if it nothing just stop
if it's a word, save it in sentence and it's first letter in acrostic (word[0] not sentence[0])
For output:
for the sentence join the words with a space : " ".join(sentence)
for the acrostic, join the letters with nothing : "".join(acrostic)
sentence = []
acrostic = []
while True:
word = input('Please enter a word, or enter to stop : ')
if not word:
break
sentence.append(word)
acrostic.append(word[0].upper())
print(" ".join(sentence))
print("-- {}".format("".join(acrostic)))
Gives
Please enter a word, or " to stop : A
Please enter a word, or " to stop : cross
Please enter a word, or " to stop : tick
Please enter a word, or " to stop : is
Please enter a word, or " to stop : very
Please enter a word, or " to stop : evil
Please enter a word, or " to stop :
A cross tick is very evil
-- ACTIVE
python 3.8 or later
sentence = []
acrostic = []
while user_input := input('word: '):
sentence.append(user_input)
acrostic.append(user_input[0].upper())
print(' '.join(sentence))
print(f"-- {''.join(acrostic)}")
output:
word: A
word: cross
word: tick
word: is
word: very
word: evil
word:
A cross tick is very evil
-- ACTIVE
python 3.6 and 3.7
sentence = []
acrostic = []
while True:
user_input = input('word: ')
if not user_input:
break
sentence.append(user_input)
acrostic.append(user_input[0].upper())
print(' '.join(sentence))
print(f"-- {''.join(acrostic)}")
python 3.5 or earlier
sentence = []
acrostic = []
while True:
user_input = input('word: ')
if not user_input:
break
sentence.append(user_input)
acrostic.append(user_input[0].upper())
print(' '.join(sentence))
print('-- {}'.format(''.join(acrostic)))
Maybe you're looking for something like this:
sentence = []
acrostic = []
word = -1
while word != "":
word = input("Word: ")
if word:
sentence.append(word)
acrostic.append(word[0].upper())
print(" ".join(sentence))
print("-- {}".format("".join(acrostic)))
Goal: To extract first letter of each word untill '' is entered.
acrostic = ""
sentence = ""
while(True):
word = input("enter a word= ")
if(word!=''):
acrostic+=word[0].upper()
sentence+=word+" "
else:
break
print(sentence)
print(acrostic)
With your sample input;
enter a word= A
enter a word= cross
enter a word= tick
enter a word= is
enter a word= very
enter a word= evil
enter a word=
output
A cross tick is very evil
ACTIVE
While everybody has you covered for basic loops, this is a nice example to use the iter(callable, sentinel) pattern:
def initial():
return input('Word: ')[:1]
print('-- ' + ''.join(iter(initial, '')))
Will produce:
Word: A
Word: cross
Word: tick
Word: is
Word: very
Word: evil
Word:
-- Active
Currently, I am working on a hangman program in python. I have the basics down, like displaying the blanks and detecting a correct letter, but I cannot figure out to detect when the word or sentence has been correctly identified.
EDIT
After reading the comments, I have updated my code, naming my variables using snake_case instead of camelCase and added an output to my show_word function.
def show_word(word, known_letters):
word = word.lower()
characters = ""
for i in word:
if i in known_letters:
characters = characters + i + " "
elif i == " ":
characters = characters + "/ "
else:
characters = characters + "_ "
print characters
return characters.replace(" ", "").replace("/", " ")
def guess_word(word, known_letters):
all_letters = "abcdefghijklmnopqrstuvwxyz"
word = word.lower()
guesses = 0
while show_word(word, known_letters) != word:
print("Guess a letter")
guess = raw_input()
if guess in known_letters:
print("You have already guessed %s" % (guess))
elif len(guess) != 1:
print("Only type one letter")
else:
known_letters += guess
guesses += 1
print("Well done you have guessed the word(s) (%s) in %s guesses" % (word, guesses))
guess_word("The quick brown fox jumps over the lazy dog", "")
The program now correctly identifies when I have guessed all the correct letters.
Thanks to everyone that helped.
My original code is below if anyone else needs help on this issue.
def showWord(word, knownLetters):
word = word.lower()
characters = ""
for i in word:
if i in knownLetters:
characters = characters + i + " "
elif i == " ":
characters = characters + "/ "
else:
characters = characters + "_ "
print characters
def guessWord(word, knownLetters):
word = word.lower()
guesses = 0
while showWord(word, knownLetters) != word:
print("Guess a letter")
guess = raw_input()
if guess in knownLetters:
print("You have already guessed %s" % (guess))
elif len(guess) != 1:
print("Only guess one letter")
else:
knownLetters += guess
guesses += 1
print("Well done, you guessed the word (%s) in %s guesses" % (word, guesses))
showWord(word, knownLetters)
guessWord("The quick brown fox jumps over the lazy dog", "")
Here is a template of some working code that you can hopefully use to figure out ways to modify your code.
def guessWord(word, knownLetters):
word = word.lower()
cur_word = ['_'] * len(word)
result_to_compare = ""
num_guesses = 0
while result_to_compare != word:
print("Guess a letter!")
guess = raw_input()
if guess in knownLetters:
print("You have already guessed this letter!")
else:
knownLetters += guess
for i in range(len(word)):
if guess is word[i]:
cur_word[i] = guess
print(cur_word)
result_to_compare = ''.join(cur_word)
print("Congrats! You guessed it!")
guessWord("severe", "")
I use cur_word as a temporary variable to show the progress the user is making. After a valid guess I create the string result_to_compare from the values in cur_word and compare it with the actual solution. Hope this helps. This will work with spaces between words as long as the user enters a space as the raw_input. You should be able to figure out how to modify it from here to work as your liking.
Your showWord() function returns None by default since it doesn't explicity return anything.
You should probably add return characters.replace(' ', '').replace('/', ' ') after print characters, and your end condition should be fulfilled.
You will need to adjust the output of showWord() since the letters won't exactly line up with word.
When showWord() actually returns your string of words, the following statment would equate properly:
while showWord(word, knownLetters) != word:
will then work as characters can be compared against word.
Also, it's Python convention to name your variables in snake_case rather than camelCase.
Finally, to redirect you for your bonus question, there are lots of people that have made ASCII Hangman in Python, perhaps you can reference, learn, and adopt those methods. If you have any issues with that, you can ask another question here on Stack Overflow, explicitly showing what you have tried.
Here's my version, I made the code as verbose as possible so it should be self explanatory.
def showWord(word,knownLetters):
word=word.lower()
characters=""
wordsofar=""
for char in word:
if char in knownLetters:
characters = characters + char + " "
wordsofar += char
elif char == " ":
characters = characters + "/ "
wordsofar += " "
else:
characters += "_ "
print characters
return validate(word, wordsofar)
def validate(word, knownLetters):
word_dict = {}
for c in word:
if c not in word_dict:
word_dict[c] = 1
else:
word_dict[c] += 1
for c in knownLetters:
if c not in word_dict:
return False
else:
word_dict[c] -=1
for k,v in word_dict.iteritems():
if v != 0:
return False
return True
and then for the while loop, you'll be checking if showWord(word, knownLetters) returns false.
My hangman program is fully functioning except there is one problem, let's say the word is mathematics, I guess m, a, t, h, e - but once I guess the other m, it says I guessed it (as opposed to saying "You already guessed this letter") but it doesn't replace the _.
My Code:
def start():
import random
words = ["barbershop", "cuddle", "furious", "demolition", "centaur", "forest", "pineapple", "mathematics", "turkish"]
word = random.choice(words);
hiddenword = len(word) * "-"
used_letters = []
lives = 6
print "Welcome to Hangman! You have 6 guesses, good luck!"
while True:
print word
print "".join(hiddenword)
guess = raw_input("> ")
hiddenword = list(hiddenword)
if len(guess) > 1:
print "Error: 1 Letter Maximum"
elif len(guess) < 1:
guess = raw_input("> ")
else:
if guess.isdigit() == True:
print "Error: Hangman only accepts letters."
else:
if guess in used_letters and word.count(guess) == 1:
print "You already guessed that letter"
else:
if guess.lower() in word:
print "You got the letter " + "'" + guess + "'" + "!"
hiddenword[word.index(guess)] = guess
used_letters.append(guess)
else:
lives -= 1
print "-1 Guesses"
print "Guesses:", lives
used_letters.append(guess)
if lives == 0:
print "GAME OVER: You're out of guesses, try again!"
break
if hiddenword == word:
print "Cangratulations, you got the word!"
break
start()
P.S. - I know I have a lot of excess code e.g. if statements, please do not comment on that.
The problem appears to be with the line:
hiddenword[word.index(guess)] = guess
The string method .index(x) returns the index of the first incidence of x. So this line will persistently fill in the first "m" in mathematics.
Assuming you want the game to reveal all instances of a letter when it is guessed (e.g., show both m's in "mathematics" when you guess "m"), you can substitute this:
for i, x in enumerate(word):
if word[i] == guess:
hiddenword[i] = guess
for your line:
hiddenword[word.index(guess)] = guess
Also, to get the "Congratulations!" message to appear, you will need to change if hiddenword == word to if ''.join(hiddenword) == word, since hiddenword is a list at this point.
Removing multiple occurences of a character in a string in python is easily achieved using:
your_string.replace("m", "");
http://www.tutorialspoint.com/python/string_replace.htm
I wrote my very muddy (apologies) code for pyg latin (taken from Codeacademy).
It works ok, except I want to add a While True... statement so that if a user puts in a number or a blank field the input box re-appears until the condition is met
pyg='gy'
original=raw_input("please enter a word")
original_lc=original.lower()
first=original_lc[0]
rest=original_lc[1:len(original_lc)]
while True:
if len(original) >0 and original.isalpha():
print "Your word: " + original_lc
if first in "aeiou":
print "your pyglatin translation: " + original_lc + pyg
else:
print "your pyglatin translation: " + rest + first + pyg
break
else:
print "You entered a blank field or a number. Please try again."
break
I know this is incorrect. Any tips?
You can put the loop at the beginning, so that the user is asked for a new input if the first one is bad:
pyg='gy'
original=raw_input("please enter a word")
# keep asking for an input until the user inputs something valid
while len(original) == 0 or not original.isalpha():
print "You entered a blank field or a number. Please try again."
original=raw_input("please enter a word")
# at this point, the input should be valid
original_lc=original.lower()
first=original_lc[0]
rest=original_lc[1:len(original_lc)]
print "Your word: " + original_lc
if first in "aeiou":
print "your pyglatin translation: " + original_lc + pyg
else:
print "your pyglatin translation: " + rest + first + pyg
The call for raw_input should be inside your loop.
while True:
pyg='gy'
original=raw_input("please enter a word")
original_lc=original.lower()
first=original_lc[0]
rest=original_lc[1:len(original_lc)]
if len(original) >0 and original.isalpha():
print "Your word: " + original_lc
if first in "aeiou":
print "your pyglatin translation: " + original_lc + pyg
else:
print "your pyglatin translation: " + rest + first + pyg
break
else:
print "You entered a blank field or a number. Please try again."
break
I'm working on a Python version of hangman that works off of a .txt file wordlist. For some reason, in playthroughs after the initial playthrough, the script won't show certain letters. Everything else works the way I want it to, more or less.
My code:
import random
wordlist = open("wordlist.txt").read().split()
word = random.choice(wordlist)
strikes = 0
hidden_letters = []
alphabet = "abcdefghijklmnopqrstuvwxyz"
guesses = []
def new_word():
global word
global guesses
word = random.choice(wordlist)
for letter in set(word):
if letter in alphabet:
hidden_letters.append(letter)
guesses = []
def current_progress():
for letter in word:
if letter in hidden_letters:
print '_',
elif letter == ' ':
print ' ',
else:
print letter,
print "\n"
def play_again():
global strikes
print "Would you like to play again?"
answer = raw_input("y/n: ")
if answer == "y":
strikes = 0
main()
elif answer == "n": exit(0)
else:
print "That's not a valid answer."
play_again()
def letter_in_word(x):
global strikes
global hidden_letters
if x in word:
hidden_letters.remove(x)
print "That letter is in the word."
current_progress()
if hidden_letters == []:
print "You win!"
play_again()
else:
print "You have %d strike(s)." % strikes
elif not x in word:
print "That letter is not in the word."
current_progress()
strikes = strikes + 1
print "You have %d strike(s)." % strikes
def main():
new_word()
current_progress()
global strikes
while strikes < 6 and not hidden_letters == []:
print "Guess a letter. \n Letters that have been already guessed are:", guesses
guess = raw_input("> ")
if guess in alphabet and len(guess) == 1:
if not guess in guesses:
guesses.append(guess)
letter_in_word(guess)
else:
print "You've already guessed that letter. Pick another."
current_progress()
print "You have %d strikes." % strikes
else:
print "Sorry, that's not a valid guess."
current_progress()
print "You have %d strikes." % strikes
if strikes == 6:
print "Oop! You lose."
print "The answer was:", word
play_again()
print "Welcome to Hangman!"
print "Six strikes and you lose."
print "----------"
main()
Your problem: when the player guesses a letter that exists in the current word and in a previous word, but was not guessed in the previous word (the player lost that game), the letter is still in the hidden_letters list because remove(x) only removes the first instance of that letter. In other words, your list contains two of the same letter during some executions, which violates an implied requirement of your code. You can fix this by adding hidden_letters = [] in your new_word() function before you add the new word's letters.
From the Python tutorial (emphasis mine):
list.remove(x)
Remove the first item from the list whose value is x. It is an error
if there is no such item.
Or, I think you could add the statement
del hidden_letters[:]
on the beggining of new_word(). It would clear the hidden_letters list.