Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

missing something in the logic or performance of this "if xxx and xxx" statement

I was thinking the way I wrote this it would only pop the last item if it was NOT a letter AND it was only over a certain length.

if test_pop.isalpha() == False and len(new_word_list) > len(word_as_list):
            new_word_list.pop()

But in at least one circumstance it is popping even if the last item is a letter.

['c', 'r', 'y']
[' _ ', ' _ ', ' _ ']
Guess a letter: y
[' _ ', ' _ ', 'y']
Guess a letter: c
['c', ' _ ', ' _ ']
Guess a letter: y
['c', ' _ ', 'y']
Guess a letter: r
['c', 'r', ' _ ']
Guess a letter: y
['c', 'r', 'y']
cry
You win!

pop removed the y twice. It seems like if I enter the last letter anything other than last, it gets popped.

  • here is the full code
import random
words = ["hi", "bye", "why", "lie", "cry", "try", "never", "ever"]
word = random.choice(words)
word_as_list = list(word)
print(word_as_list)
new_word_list = []
# make placeholders in new_word_list
for letter in word:
    new_word_list.append(" _ ")
print(new_word_list)
while True:
    letter_guess = input("Guess a letter: ")
    if letter_guess in word_as_list:
        # get index of letter guess
        index_value = (word_as_list.index(letter_guess))
        # insert letter guess it index
        new_word_list.insert(index_value, letter_guess)
        test_pop = new_word_list.pop()
        if test_pop.isalpha() == False and len(new_word_list) > len(word_as_list):
            new_word_list.pop()
            print(new_word_list)
        else:
            print(new_word_list)

            if new_word_list == word_as_list:
                print("".join(new_word_list))
                print("You win!")
                break

2 Answers

Chris Howell
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Chris Howell
Python Web Development Techdegree Graduate 49,703 Points

So you have a few issues here, 1 I would say order of conditionals and how you are checking your lists. Though it does know how to tell if you completely a word which is good. But I am also able to repeatedly enter the same character and it would fill with that character. Without writing out all the code for you, I will try to explain and give examples.

Current code output issue:

['b', 'y', 'e']
[' _ ', ' _ ', ' _ ']
Guess a letter: b
['b', ' _ ', ' _ ']
Guess a letter: b
['b', 'b', ' _ ']
Guess a letter: b
['b', 'b', 'b']
Guess a letter: y
['b', 'y', 'b']
Guess a letter: y
['b', 'y', 'y']
Guess a letter: e
['b', 'y', 'e']
bye
You win!

Take another look at the order of your conditional. Else alone is a catch all for the IF statement

# No matter what I did, this check never passes for me. So else always runs.
if test_pop.isalpha() == False and len(new_word_list) > len(word_as_list):

If that condition fails, it prints the the list out again, does a check for a win then starts inserting characters again.

Ideally you want to do your conditional checks. And if it meets each check THEN modify your list before displaying it.

The steps you are taking look like this:

Get Value -> Modifying a List-> Check Value against condition(s) -> Print Value

You want to:

Get Value -> Check that value against condition(s) -> Modifying A List-> Print value

Here is a simple Pseudocode version of how I would handle the initial set up.

while True:
    # Display list with underscores 
    # Get User's Guess
    # Get and store the index of that guess from the randomly chosen word
    # IF I get an index back (then it exists)
      # INSERT into my list with underscores,
      #  value at the stored index inside randomly chosen word variable
      # IF new_word_list equals word_as_list:
        # Then display Win and be sure to break

    # ELSE display to user to try again
      # let loop cycle around again
Chris Howell
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Chris Howell
Python Web Development Techdegree Graduate 49,703 Points

This still would essentially still have an issue though, If I am a User and the word is suppose to be 'ever'. There are two e's. But when i grab an index it grabs the first one it encounters only. That means when I do an insert, it will only insert 1 e when it should fill all spots where an e exists.

If you want to go that far with the logic, there are a few ways. 1 would be to write a for loop that loops over the word characters in that list grabbing the indices where the guess matches the value of the current list item.

you would have to build out a list of indices, then you would also need to loop again to do your inserts of that 1 character value into the new_list, if that makes sense?

This would then let you do this:

['n', 'e', 'v', 'e', 'r']
[' _ ', ' _ ', ' _ ', ' _ ', ' _ ']
Guess a letter: e
[' _ ', 'e', ' _ ', ' e', ' _ ']

Maybe you addressed this, and I apologize if you did.. I will go back through your post, there's lots of good info there. The thing I was trying to compensate for is: when a correct letter guess is inserted, the length of that list is increased by one, and the underscores keep adding up.
I'm sure this is not the most elegant way to do this, I learn by exploring. As far as repeating characters, I just didn't get to that part yet. I really wanted the underscores for placeholders right at the start. But then from there more and more issues keep coming up. Thanks for your help.

Chris Howell
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Chris Howell
Python Web Development Techdegree Graduate 49,703 Points

No worries, I dont think I actually explored the increasing list issue you are talking about.

The program overall worked for me, with the exception of the bugs I noted. But I will go back and print out some list sizes and see what changes happen with it. I shall return.

Thanks Chris, That is what I tried in one of my earlier attempts looping and entering all matching letters at once. There was another problem that arose with that and I was told looping over an array and modifying it would cause occasional unpredictable results...which it did. Well thanks, I guess I've taken this as far as I can for now. Back to the videos :D

Chris Howell
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Chris Howell
Python Web Development Techdegree Graduate 49,703 Points

Okay to answer your issue about the increasing list size.

This has to do with your this line:

new_word_list.insert(index_value, letter_guess)

What is happening here is calling .insert takes a parameter of an index which you are passing it.

So you are telling the list EXACTLY where you want to place this item, so then the list will place it in that spot but it will shift the other indexes over 1.

Example:

# here is some list of numbers

num_list = [ 1, 2, 3, 4, 5, 6 ]
#indices    [ 0, 1, 2, 3, 4, 5 ]

# I want to insert a number 10 at index 2
num_list = [ 1, 2, 10, 3, 4, 5, 6 ]
#indices    [ 0, 1, 2, 3, 4, 5, 6 ]

Notice it didnt replace that index it just moved the others over

If I want to replace it I could essentially do this.

# 2 is my index. I am setting list index 2's value to 10.

num_list[2] = 10

If I could give you two best answers I would. Thanks.