'Optimizing Wordle Bot with Python - Search for a word that contains a, b, and c?

I have been working on writing a Wordle bot, and wanted to see how it preforms with all 13,000 words. The problem is that I am running this through a for loop and it is very inefficient. After running it for 30 minutes, it only gets to around 5%. I could wait all that time, but it would end up being 10+ hours. There has got to be a more efficient way. I am new to python, so any suggestions would be greatly appreciated.

The code here is the code that is used to limit down the guesses each time. Would there be a way to search for a word that contains "a", "b", and "c"? Instead of running it 3 separate times. Right now the containts, nocontains, and isletter will each run every time I need to search for a new letter. Searching them all together would greatly reduce the time.

#Find the words that only match the criteria
def contains(letter, place):
    list.clear()
    for x in words:
        if x not in removed:
            if letter in x:
                if letter == x[place]:
                    removed.append(x)
                else:
                    list.append(x)
            else:
                removed.append(x)
def nocontains(letter):
    list.clear()
    for x in words:
        if x not in removed:
            if letter not in x:
                list.append(x)
            else:
                removed.append(x)
def isletter(letter, place):
    list.clear()
    for x in words:
        if x not in removed:
            if letter == x[place]:
                list.append(x)
            else:
                removed.append(x)


Solution 1:[1]

I just wrote a wordle bot that runs in about a second including the web scraping to fetch a list of 5 letter words.

import urllib.request
from bs4 import BeautifulSoup

def getwords():
    source = "https://www.thefreedictionary.com/5-letter-words.htm"
    filehandle = urllib.request.urlopen(source)
    soup = BeautifulSoup(filehandle.read(), "html.parser")
    wordslis = soup.findAll("li", {"data-f": "15"})
    words = []
    for k in wordslis:
        words.append(k.getText())
    return words

words = getwords()

def hasLetterAtPosition(letter,position,word):
    return letter==word[position]

def hasLetterNotAtPosition(letter,position,word):
    return letter in word[:position]+word[position+1:]

def doesNotHaveLetter(letter,word):
    return not letter in word

lettersPositioned = [(0,"y")]
lettersMispositioned = [(0,"h")]
lettersNotHad = ["p"]

idx = 0
while idx<len(words):
    eliminated = False
    for criteria in lettersPositioned:
        if not hasLetterAtPosition(criteria[1],criteria[0],words[idx]):
            del words[idx]
            eliminated = True
            break
    if eliminated:
        continue
    for criteria in lettersMispositioned:
        if not hasLetterNotAtPosition(criteria[1],criteria[0],words[idx]):
            del words[idx]
            eliminated = True
            break
    if eliminated:
        continue
    for letter in lettersNotHad:
        if not doesNotHaveLetter(letter,words[idx]):
            del words[idx]
            eliminated = True
            break
    if eliminated:
        continue
    idx+=1

print(words) # ["youth"]

The reason yours is slow is because you have a lot of calls to check if word in removed in addition to a number of superfluous logical conditions in addition to going through all the words for each of your checks.

Edit: Here's a get words function that gets more words.

def getwords():
    source = "https://wordfind-com.translate.goog/length/5-letter-words/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp"
    filehandle = urllib.request.urlopen(source)
    soup = BeautifulSoup(filehandle.read(), "html.parser")
    wordslis = soup.findAll("a", {"rel": "nofollow"})
    words = []
    for k in wordslis:
        words.append(k.getText())
    return words

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1