如何加速Python中Wordle回测函数以处理13000个单词?
优化Wordle起始词回测速度的方案
我正在寻找最优的Wordle起始词,为此写了一个回测函数——通过统计起始词能从13000个单词的词表中消除多少单词来评估优劣。比如用PLANE当起始词时,会移除所有包含P、L、A、N、E的单词,计算消除比例判断好坏,调用backtest(starter="plane")会返回('plane', '87.37%')。
但把13000个单词全部代入回测时,运行速度慢到难以接受。我试过把词表创建部分移出回测函数,但会不小心修改原始词表;知道有多线程方案但觉得实现难度高,希望得到其他可行的加速方法。
现有代码
创建词表
words = [] with open('list.txt') as f: for line in f: words.append(line.strip())
回测函数
def backtest(starter): # 每次都重新加载词表 words = [] with open('list.txt') as f: for line in f: words.append(line.strip()) total = len(words) guess = starter result = "#####" tupleX = tuple(words) for word in tupleX: for i in range(5): if result[i] == "#" and guess[i] in word: words.remove(word) break pct = round(100 - (len(words)/total*100), 2) return guess, ("{}%".format(pct))
回测并写入DataFrame
import pandas as pd data = [] for i in words: hold = backtest(starter=i) data.append(hold) bruteForce = pd.DataFrame(data, columns=['Word','Score']) bruteForce = bruteForce.sort_values(by=['Score'], ascending=False) bruteForce
核心优化方案
1. 只加载一次词表,回测时复制使用
原来的backtest函数每次都重新读取文件加载词表,IO操作是巨大的性能瓶颈。可以把词表加载逻辑提到函数外,回测时复制一份列表,既避免重复IO,又不会修改原始词表:
# 全局加载一次词表,后续所有回测复用 with open('list.txt') as f: original_words = [line.strip() for line in f] total_words = len(original_words)
2. 用集合优化字符检查逻辑,替换低效的循环+remove
原来的嵌套循环+list.remove()操作效率极低:remove每次都要遍历列表找元素,时间复杂度是O(n);字符串的in操作也是O(k)(k是字符串长度)。改用集合做字符检查,配合列表推导式一次性筛选,性能会大幅提升:
def backtest(starter): # 把起始词转成字符集合,O(1)时间复杂度的成员检查 starter_chars = set(starter) # 列表推导式筛选出不包含起始词任何字符的单词 remaining = [word for word in original_words if not any(c in starter_chars for c in word)] pct = round(100 - (len(remaining)/total_words * 100), 2) return starter, f"{pct}%"
3. 预计算所有单词的字符集合,避免重复计算
可以提前把每个单词的字符集合预存在字典里,回测时直接取用,省去每次遍历单词字符的时间:
# 预计算每个单词的字符集合,只做一次 word_char_sets = {word: set(word) for word in original_words} def backtest(starter): starter_chars = set(starter) # 直接用预存的字符集合做交集检查,更快 remaining = [word for word in original_words if starter_chars.isdisjoint(word_char_sets[word])] pct = round(100 - (len(remaining)/total_words * 100), 2) return starter, f"{pct}%"
4. 用列表推导式代替for循环追加数据
回测时生成数据列表可以直接用列表推导式,比手动循环append更高效:
import pandas as pd # 列表推导式一次性生成所有结果 data = [backtest(word) for word in original_words] bruteForce = pd.DataFrame(data, columns=['Word','Score']) bruteForce = bruteForce.sort_values(by=['Score'], ascending=False) print(bruteForce)
优化效果说明
这些改动主要解决了三个核心性能问题:
- 消除了13000次重复文件IO操作
- 把嵌套循环+O(n)的
remove操作替换成O(m)的列表推导式(m是词表长度) - 用集合的O(1)成员检查代替字符串的O(k)检查,还通过预计算进一步减少重复计算
实际测试中,优化后的代码运行速度能提升几十甚至上百倍。
内容的提问来源于stack exchange,提问作者StayShmacked
相关产品推荐
相关产品推荐

