Hi everyone i'm very new to python , only have been working with it for about a week, and I have the following question.I'm making a Lingo game in which you guess a needed word, but the first letter is always given when started

I have 3 lists in which i'm adding words seperated per letter so for example:

# neededword is the word you need to guess
neededwordlist=


#this is the raw input of the user for example now i entered :
rawlist =


# mask is the return of a string of a method which checks if any letters are matched and then puts a '*' on incorrect letters which i then add to a list.
masklist =

i then convert them to sets to make it easier and that's worked pretty well .I've experimented for many hours and my problem is as follows, I can find the matching letter which are in the wrong order and print them, but I can't seem to find a way to print them when i have 2 of the same letters in the list for example:

word to guess : apples
raw input: aplpes
it will print out set[l]
but it won't check for the 2nd 'p' as it has already found there is a 'p' in both lists.

Is there any way to solve this or any other way to do this , any help is appreciated :)

Sets maybe be easier, but as you've found, they're wrong.

Consider the following -

>>> word = "fishcakes"
>>> list(word)
['f', 'i', 's', 'h', 'c', 'a', 'k', 'e', 's']
>>> set(word)
set(['a', 'c', 'e', 'f', 'i', 'h', 'k', 's'])
>>> set(word) == list(word)
False
>>> ''.join(set(word)) == word
False
>>> ''.join(list(word)) == word
True

Set elements are unique - as such, you can't have a set with two identical elements in.
The same is not true of lists

For these reasons, set is not the correct data structure to use. list is suitable, and if you want a feature complete version, define your own class for the word.

Edited 5 Years Ago by Enalicho: n/a

Comments
Thanks so much for the explanation!

You can use the following

neededwordlist= ['a','p','p','l','e']
rawlist = ['a','l','p','p','e']

need, raw = list(neededwordlist), list(rawlist) # make copies
for i in range(min(len(need), len(raw))):
    if need[i] == raw[i]:
        need[i] = raw[i] = '!'
wrongposition = set(need) & set(raw)
wrongposition.discard('!')
print wrongposition

""" --> my output
set(['p', 'l'])
"""

The idea is that the letters in wrong positions are the letters which still belong to both lists after all the correct matches have been removed.

Edited 5 Years Ago by Gribouillis: n/a

Comments
simple and clear explanation thanks!

Thanks so very much for your support and explanation , so best to use a set if you don't want duplicates and list for if u do want duplicates. Didnt' expect a reply so fast + 1 for you guys :) and the community

Thanks a lot for your input but I have 1 more problem with the following , I implemented the code into the following :

def wrongletters(self,input):
            neededword= self.neededWord
            raw=input
            neededwordlist = []; rawlist=[]

            for nletter1 in neededword:#add letters into lists
                neededwordlist.append(nletter1)

            for rletter2 in raw:
                rawlist += rletter2

            need, raw = list(neededwordlist), list(rawlist) # make copies
            for i in range(min(len(need), len(raw))):
                if need[i] == raw[i]:#if same letters    
                    need[i] = raw[i] = '!'
                wrongposition = set(raw) & set(need)
                wrongposition.discard('!')
#                    Wrongposition=list(wrongposition)#convert back to a list

                print"".join(list(wrongposition))

and I call this method here :

def guessAWord(self):
        attempt=5
        
        check=Checks()
        check.neededWord=self.words.getNextRandomWord()
        input="      "
        mask = check.getMask(input)
        
        while attempt>0 and check.wordguessed==False :
            attempt -=1
            input=raw_input(mask)
            mask = check.getMask(input)
            check.wrongletters(input)
            
            
            
            

        return check.wordguessed

The problem now is that its returning me multiple strings
that are being printed for example my word to guess is banana so i start with b******:

b*****bonano
an
an
an
n

its returning me the wrong letters here i should only be getting back an 'a'

now if my word to guess is apples:

a*****seplas
apsel
apsel
asel
ase
ase
ae
a*pl*s

I have no idea whats going wrong now :( would love to here your input

Lines 16 to 20 should not be under the for loop. Watch the code indention.

Really appreciate the help ! outstanding

neededwordlist= ['a','p','p','l','e']
    rawlist = ['a','l','p','p','e']
     
    need, raw = list(neededwordlist), list(rawlist) # make copies
    for i in range(min(len(need), len(raw))):
        if need[i] == raw[i]:
            need[i] = raw[i] = '!'
    wrongposition = set(need) & set(raw)
    wrongposition.discard('!')
    print wrongposition
     
    """ --> my output
    set(['p', 'l'])
    """

Does this mean any list contents that match are a '!' and then u discard them ?
I would like to know what exactly the red colored text does, if i need it again in the future ,thanks in advance.

Add print statements to see what it does

neededwordlist= ['a','p','p','l','e']
rawlist = ['a','l','p','p','e']

need, raw = list(neededwordlist), list(rawlist) # make copies
for i in range(min(len(need), len(raw))):
    if need[i] == raw[i]:
        need[i] = raw[i] = '!'
    print "i = ", i
    print need
    print raw
wrongposition = set(need) & set(raw)
print wrongposition
wrongposition.discard('!')
print wrongposition

""" my output -->
i =  0
['!', 'p', 'p', 'l', 'e']
['!', 'l', 'p', 'p', 'e']
i =  1
['!', 'p', 'p', 'l', 'e']
['!', 'l', 'p', 'p', 'e']
i =  2
['!', 'p', '!', 'l', 'e']
['!', 'l', '!', 'p', 'e']
i =  3
['!', 'p', '!', 'l', 'e']
['!', 'l', '!', 'p', 'e']
i =  4
['!', 'p', '!', 'l', '!']
['!', 'l', '!', 'p', '!']
set(['!', 'p', 'l'])
set(['p', 'l'])
"""

There are other ways to do it, for python gurus, like

A, B = (set(x) for x in zip(*((a,b) for (a,b) in zip(neededwordlist, rawlist) if a != b)))
wrongposition = A & B

Edited 5 Years Ago by Gribouillis: n/a

I think set intersection is insufficient to give hints properly for misplaced letters. You should also know what you want to say if user inputs one letter in wrong place and there is such letter in two other places. List representation is not needed but we can use string directly for zip.

>>> needed = 'apple'
>>> guess = 'alxpe'
>>> indexes, a, b = zip(*((ind, char, charn) for ind, (char, charn) in enumerate(zip(*(needed, guess))) if char != charn))
>>> wrong = [(ind, c1, c2) for ind, c1, c2 in zip(indexes, a, b) if c2 in a]
>>> wrong
[(1, 'p', 'l'), (3, 'l', 'p')]
>>> set(a) & set(b)
set(['p', 'l'])
>>> guess = 'elppa'
>>> wrong = [(ind, c1, c2) for ind, c1, c2 in zip(indexes, a, b) if c2 in a]
>>> wrong
[(1, 'p', 'l'), (3, 'l', 'p')]
>>>

Edited 5 Years Ago by pyTony: n/a

Time finished to update, so the previous second example was left scrambled. I did not re-evaluate the help variables:

>>> guess = 'elppa'
>>> indexes, a, b = zip(*((ind, char, charn) for ind, (char, charn) in enumerate(zip(*(needed, guess))) if char != charn))
>>> wrong = [(ind, c1, c2) for ind, c1, c2 in zip(indexes, a, b) if c2 in a]
>>> wrong
[(0, 'a', 'e'), (1, 'p', 'l'), (3, 'l', 'p'), (4, 'e', 'a')]
>>>

Disclaimer: I only know MasterMind, not Lingo.

Edited 5 Years Ago by pyTony: n/a

def wrongletters(self,input):
    neededword= self.neededWord
    raw=input
    neededwordlist = []; rawlist=[]
     
    for nletter1 in neededword:#add letters into lists
    neededwordlist.append(nletter1)
     
    for rletter2 in raw:
    rawlist += rletter2
     
    need, raw = list(neededwordlist), list(rawlist) # make copies
    for i in range(min(len(need), len(raw))):
    if need[i] == raw[i]:#if same letters
    need[i] = raw[i] = '!'
    wrongposition = set(raw) & set(need)
    wrongposition.discard('!')
    # Wrongposition=list(wrongposition)#convert back to a list
     
    print"".join(list(wrongposition))

It's finally working, thanks for all the help and explanations. Now I'm just completely stuck on how I would go about unittesting this method. I've been at it for 2 hours now , whilst the other method I made a unittest for was so easy to make . Is there any easy way to use unittest to test this method ?

This article has been dead for over six months. Start a new discussion instead.