iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python利用字典树实现猎词游戏
  • 690
分享到

Python利用字典树实现猎词游戏

2024-04-02 19:04:59 690人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录解决策略什么是 Trie?创建 Trie 字典树单词测试总结猎词(Word hunt)是一类很常见的游戏,给你一张字母组成的表,然后让你在这些字母中尽可能多的去寻找单词。这类游戏

猎词(Word hunt)是一类很常见的游戏,给你一张字母组成的表,然后让你在这些字母中尽可能多的去寻找单词。这类游戏有不同的变体,一类是你可以多次重复使用这些字母(这类游戏叫做猎词),或者你只能使用一次每个字母(这类游戏叫做字母重组)。你组出来的单词越长就得分越高,使用了所有字母就可以获得最高分。

这类游戏对计算机而言是很「容易」去完成的,而且要强调一个相当有用的数据结构叫做 “Trie”。

解决策略

让我们先拿出一个单词「MAINE」

首先要做的决定我们要如何处理这个问题。如果问题是字母重组,那么我们可以尝试所有可能的字母组合,然后看看它们是否是单词。这对字母重组是一个还不错的解决方案,但是对猎词而言就不能给我们多少帮助了,因为字母可以被重用。所以当你可能发现了单词 ”name” 时,你将再不会发现单词 “nine”。显然我们不能尝试穷尽这些字母所有可能的组合,因为我们不知道一个单词可能被重复多少次。因为这个原因,我们退步为搜索一个词典,去看这个词是否可以只由我们拥有的字母组成。当有一个很大的词典时,这可能耗费大量的时间,并且你每次换了一个词时都必须重复这一步。

作为替代,我们需要一个搜索词典的方法,可以快速告诉我们某个单词是否在词典中。这就是预测性文本结构 Trie 字典树的用武之地。

什么是 Trie?

Trie 是一个树数据结构 — 作为原本树节点储存一个与 key 相关联的值的代替 — 这个节点现在储存 key 本身。节点中的值可用于根据遍历次数来为某些叶子节点或概率值分配顺序。

维基百科中一个 Trie 的例子

上面这个 Trie 的例子由 “A”,“to”,“tea”,“ted”,“ten”,“i”,“in” 和 “inn” 生成。一旦一个像这样的 Trie 字典树结构被生成,去判断任何一个单词是否在这个 Trie 字典树中就是 O(n) 复杂度的。如果我在搜索 “ted”,我会消耗 O(1) 去寻找 “t”,然后从 “t” 节点再消耗 O(1) 去寻找 “e”,并且再从 “te” 节点消耗 O(1) 去到 “d”。

面对问题“这一堆字母在不在这个词典中?”,这就是一个「非常」快速的解答方案。我们首先要做的就是构建词典。

python 中,这个步骤很简单。每个节点的样子都应该是一个词典。所以我们需要从一个空词典开始,然后对词典中的每一个单词,逐字母的检查下一个字母是否在我们的 Trie 字典树结构中,如果不在就添进去。现在,这听起来相当耗费时间,在某些方面也的确如此,但是它只需要完成一次。当 Trie 被建好后,你可以直接使用它而无需任何其它开销。

创建 Trie 字典树

我们需要从一个装满所有可能单词的列表开始(网上有很多这类资源),然后我们的词典加载函数可能长下面这样:

def load():
    with open('words.txt') as wordFile:
        wordList = wordFile.read().split()
 
    trie = {}
    for word in wordList:
        addWordToTrie(trie, word)
   
    return trie

我们需要一个函数来给 Trie 中添加单词。我们通过快速浏览 Trie 来检查每一个字母,判断我们是否需要添加一个新的 key。因为我们通过 key 来检索 Python 中的字典,所以无需在每个节点储存一个 value。这是一个有自己的 key 值的新词典。

def addWordToTrie(trie, word, idx = 0):
    if idx >= len(word):
        return       
    if word[idx] not in d:
        d[word[idx]] = {}
    addWordToTrie(d[word[idx]], word, idx+1)

这里有一个简单的想法。我们接收的参数是当前所在位置的 Trie 字典树(注意在这个例子中,Trie 中的所有节点也是一个 Trie),这个单词,以及我们所查看的字母在单词中的索引

如果索引超过了单词的长度,我们就停止!如果没有超过,我们需要检查是否这个字母已经在这个 Trie 中。如果这个字母不在这个 Trie 的下一层中,那么我们添加一个新的字典在这一层,当前这个字母就是字典的 key。然后,我们递归的调用这个函数,并且传入我们当前字母对应的词典(也就是 Trie),这个单词,以及下一个索引位置。

使用这两个函数,我们就构建了上面展示的 Trie 字典树。但是有一个问题摆在我们面前。我们如何知道我们找到的是一个「单词」,而不是一个真正的单词的前一「部分」呢?例如,在上面这个 Trie 的例子中,我们希望 “in” 可以像 “inn” 一样返回是一个单词,但是并不希望将 “te” 作为一个词典中的单词来返回。

为了完成这一点,当我们完成一个单词时,「必须」在这个节点中储存一个值。来回头重新审视一下我们的 addWordToTrie 函数,如果这个节点表示一个完整的单词,就将 “leaf” 这个 key 设置为 “True”。

def addWordToTrie(d, word, idx):
    if idx >= len(word):
        d['leaf']=True
        return
    if word[idx] not in d:
        d[word[idx]] = {'leaf':False}
    addWordToTrie(d[word[idx]], word, idx+1)

现在,无论何时我们完成一个单词,都要设置当前这个词典节点的 “leaf” 值为 True,或者我们添加一个新的节点,它的 “leaf” 值为 “False”。

当我们加载这个函数初始化时,应该是同样的设置 {‘leaf’:False},所以我们就无需再拿一个空的字符串来作为有效词的返回。

就是这样!我们已经创建了我们的 Trie 结构,接下来啥时候使用它了。

单词测试

找一个办法来进行尝试:从一个空的列表开始。对我们单词中的每个字母,检查我们的 Trie 字典树,看它是否在其中。如果在,就拿到这个词典子树再重新开始(这样我们可以检查重复的字母)。保持这样进行下去,直到我们找到一个 leaf 标志位为 true 的节点,或者我们在下一层的词典子树中找不到单词中的任何字母。如果我们发现了一个标记为 leaf 的节点,就把这个单词添到列表中。如果我们没有找到下一个词典子树,就返回并执行下一个字母。

def findWords(trie, word, currentWord):
    myWords = [];
    for letter in word:
        if letter in trie:
            newWord = currentWord + letter
            if (trie[letter]['leaf']):
                myWords.append(newWord)
            myWords.extend(findWords(trie[letter], word, newWord))
    return myWords

这里注意一下,我们正在构建一个新单词传递到列表中,但是我们也会递归的去寻找新的单词,用来扩展我们的列表。

有的读者可能已经发现了接下来的问题。如果字母重复怎么办呢?例如我们的单词是 “「TEEN」”,并且我们现在在 “TE” 节点上,我们已经在子树上检查了 “t“,这很好,然后我们在子树上检查 ”e“ 并发现 ”tee“ 是一个单词。我们将 ”tee“ 添加到列表中。但是单词的下一个字母又是 ”e“,所以我们再次找到了 ”tee“。有一些方法去解决这个问题,但是最简单的方法之一就是用集合代替列表。

def findWords(trie, word, currentWord):
    myWords = set()      
    for letter in word:
        if letter in trie:
            newWord = currentWord + letter
            if trie[letter]['leaf']:
                myWords.add(newWord)
            myWords = myWords.uNIOn(findWords(trie[letter], word, newWord))
    return myWords
 

现在无论我们把同一个单词找到多少次,我们都可以保证列表中的唯一性。我们也可以将输入单词中的字母去重,进而节约处理时间。

就这样!利用这三个函数就可以通过我们输入的字母来找到所有可能在字典中的单词。来让我们把这些包到一个 main 函数里面,然后给一个输入,具体步骤我们已经完成了。

def main():
    print('Loading dictionary...')
    wordTrie = load()
    print('Done\n')
 
    word = raw_input("What letters should we use: ")
    minLength = int(raw_input("What is the minimum word length: "))
    print("")
 
    count = 0;
    for word in sorted(findWords(wordTrie, word, "")):
        if len(word) >= minLength:
            count = count+1
            print(word)
    print(str(count) + " words found.")

因为我们不是单词重组,所以我们找到了「太」多单词。使用上面提到的例子「MAINE」和一个我找到的词典 — 大约有 370000 个单词 — 这个程度发现了 208 个单词。这也是为什么我添加了一个最短单词长度的原因。限制单词长度至少为七,我们可以得到如下结果:

Loading dictionary…
 
Done
 
What letters should we use: maine
 
What is the minimum word length: 7
 
amninia
 
anaemia
 
anamnia
 
animine
 
emmenia
 
enamine
 
manienie
 
mannaia
 
meminna
 
miminae
 
minaean
 
11 words found.

加载词典消耗了大约半秒,后面的查找单词基本上感受不到明显的时间消耗。

为了一个单词去每次都重新建树是很低效的,所以最好可以重用它,要么是保存整个数据结构,要么尝试一次循环的查找多个单词。

总结

但愿这篇文章可以为你提供一个 Trie 的基本介绍,便于你去解决一些单词问题。当你想要一些自动补充完成的任务时,Trie 是一个很好用的数据结构。短信,搜索甚至是指引方向,都可以使用系统中的数据构建 Trie 来帮助预测用户下一步想要输入什么。正如我们所看到的,它也是在一个搜索大量的现有路径时很好的结构,在这个例子中,这个路径就是有效的单词。

以上就是Python利用字典树实现猎词游戏的详细内容,更多关于Python字典树的资料请关注编程网其它相关文章!

--结束END--

本文标题: Python利用字典树实现猎词游戏

本文链接: https://www.lsjlt.com/news/118719.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python利用字典树实现猎词游戏
    目录解决策略什么是 Trie?创建 Trie 字典树单词测试总结猎词(word hunt)是一类很常见的游戏,给你一张字母组成的表,然后让你在这些字母中尽可能多的去寻找单词。这类游戏...
    99+
    2024-04-02
  • Python如何利用字典树实现猎词游戏
    本篇内容主要讲解“Python如何利用字典树实现猎词游戏”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python如何利用字典树实现猎词游戏”吧!猎词(word hunt)是一类很常见的游戏,给...
    99+
    2023-07-02
  • Python+Tkinter实现经典井字棋小游戏
    目录演示介绍官方文档tkinter.messagebox源码演示 介绍 首先来介绍一下GUI库Tkinter 主要模块: tkinter Main Tkinter module....
    99+
    2024-04-02
  • python猜单词游戏的实现
    目录1.游戏思路和流程图2. 单词库和模块3. 游戏开始提示4. 重新开始游戏输入验证5. 用户输入验证6. 猜词判断(游戏核心)7. 游戏完成度提示8. 游戏核心外壳9. 游戏外壳...
    99+
    2024-04-02
  • 怎么用Python+Tkinter实现经典井字棋小游戏
    这篇文章主要讲解了“怎么用Python+Tkinter实现经典井字棋小游戏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用Python+Tkinter实现经典井字棋小游戏”吧!演示介绍首...
    99+
    2023-06-29
  • JAVA使用前缀树(Tire树)实现敏感词过滤、词典搜索
    目录简介Trie树code结论简介 有时候需要对用户输入的内容进行敏感词过滤,或者实现查找文本中出现的词典中的词,用遍历的方式进行替换或者查找效率非常低,这里提供一个基于Trie树的...
    99+
    2023-01-03
    JAVA前缀树敏感词过滤 JAVA前缀树
  • 利用JetpackCompose实现经典俄罗斯方块游戏
    目录可组合函数游戏机身 - TetrisBody游戏按钮 - TetrisButton游戏屏幕 - TetrisScreen调度器 - TetrisViewModel项目地址你的童年...
    99+
    2024-04-02
  • 利用C语言实现经典游戏斗兽棋
    效果图 核心代码 #include<stdio.h> #include<easyx.h> #include<stdlib.h> #include...
    99+
    2024-04-02
  • 基于Python实现英语单词小游戏
    目录导语一、敲代码之前的小tips二、运行环境三、素材(图片等)四、代码展示1)主程序(英文打字小游戏主入口模块)2)游戏配置信息模块3)游戏视图模块4)PyGame游戏精灵模块五、...
    99+
    2022-11-16
    Python英语单词游戏 Python 单词游戏 Python 游戏
  • 利用C语言实现n字棋游戏
    目录前言思路效果图开始的界面棋盘的样子随机打的坐标获得胜利结束程序代码test.cgame.cgame.h前言 这里就简单发一个n字棋游戏,和井字棋一样,不过这个游戏你可以自定义棋盘...
    99+
    2024-04-02
  • Python+Pygame实现经典魂斗罗游戏
    目录一、效果展示二、操作说明三、核心代码今天分享一个经典小游戏魂斗罗的 Python 版实现。 一、效果展示 二、操作说明 A:向左 D:向右 W:跳起 S:趴下 J:射击 P:退...
    99+
    2024-04-02
  • 基于JS实现经典的井字棋游戏
    目录先看成品游戏初始化界面:玩家获胜AI电脑获胜思路生成棋盘重新开始玩家落子电脑落子代码HTMLCSSjs井字棋作为我们在上学时代必玩的一款连珠游戏,你知道如何做到先手必然不会输吗?...
    99+
    2024-04-02
  • 利用C语言实现猜数字小游戏
    本文实例为大家分享了C语言实现猜数字小游戏的具体代码,供大家参考,具体内容如下 实现猜数字的游戏: 要用程序完成以下几步: 1、电脑自动生成随机数(1到100之间的数字) 2、玩家输...
    99+
    2024-04-02
  • Python实现四个经典小游戏合集
    目录 一、效果展示1、俄罗斯方块2、扫雷3、五子棋4、贪吃蛇二、代码展示1、俄罗斯方块2、扫雷3、五子棋4、贪吃蛇 一、效果展示 1、俄罗斯方块 这个应该是玩起来最最简单的了… 2...
    99+
    2024-04-02
  • 基于Python+Pygame实现经典赛车游戏
    目录导语一、环境安装二、代码展示1.主程序main.py2.地图设置maps.py三、效果展示1.游戏界面2.游戏运行中3.15分到手导语 哈喽!哈喽~我是木木子,很久没给大家更新游...
    99+
    2024-04-02
  • Python实现猜数字小游戏
    首先需求一共有五次猜测机会,在五次机会中才对就赢了,结束游戏,五次都猜错就输了,也结束游戏。首先先画个草图,这是我画的草图 再根据草图编写一个窗口,一个Label,一个Entry,...
    99+
    2024-04-02
  • 利用Python编写数字战舰游戏
    本篇内容主要讲解“利用Python编写数字战舰游戏”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“利用Python编写数字战舰游戏”吧!前言制造多艘战舰:你需要小心,因为你需要确保你不要在战斗板上...
    99+
    2023-06-02
  • 利用Java实现简单的猜数字小游戏
    目录实现思路代码实现实现思路 由计算机随机产生1~100的整数。用户猜测计算机产生的数字,并输入数字,当输入的数字与计算机产生的数字相同时输出恭喜你,猜对了。当输入的数字小于计算机产...
    99+
    2024-04-02
  • 如何利用Python实现星空大战游戏
    小编给大家分享一下如何利用Python实现星空大战游戏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一.游戏画面二.游戏结束画面三.游戏素材四.游戏代码星空飞碟大...
    99+
    2023-06-29
  • 利用python实现flappy bird 游戏(完整代码)
    第一个python文件,flappybirdmain.py ,程序中已经有详细注释.。 程序大概流程:1.加载图片素材文件 2.绘画开始界面,等待程序开始(按空格) 3 .程序刷新,...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作