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

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

2023-07-02 09:07:23 822人浏览 泡泡鱼

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

摘要

本篇内容主要讲解“python如何利用字典树实现猎词游戏”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python如何利用字典树实现猎词游戏”吧!猎词(Word hunt)是一类很常见的游戏,给

本篇内容主要讲解“python如何利用字典树实现猎词游戏”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习Python如何利用字典树实现猎词游戏”吧!

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

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

解决策略

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

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

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

什么是 Trie?

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

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

维基百科中一个 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.

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

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

到此,相信大家对“Python如何利用字典树实现猎词游戏”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

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

本文链接: https://www.lsjlt.com/news/341103.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+Tkinter实现经典井字棋小游戏
    这篇文章主要讲解了“怎么用Python+Tkinter实现经典井字棋小游戏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用Python+Tkinter实现经典井字棋小游戏”吧!演示介绍首...
    99+
    2023-06-29
  • 如何利用Python实现星空大战游戏
    小编给大家分享一下如何利用Python实现星空大战游戏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一.游戏画面二.游戏结束画面三.游戏素材四.游戏代码星空飞碟大...
    99+
    2023-06-29
  • 如何使用Java实现经典游戏2048
    这篇文章主要介绍如何使用Java实现经典游戏2048,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!主要设计游戏面板生成显示方块设计键盘监听,方向键控制数字移动数字移动逻辑算法处理数字累加到2048,游戏胜利功能截图游...
    99+
    2023-06-29
  • python如何实现可排序词典
    这篇文章给大家分享的是有关python如何实现可排序词典的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。可排序词典>>> m = d...
    99+
    2024-04-02
  • 如何利用C语言实现猜数字小游戏
    这篇文章主要讲解了“如何利用C语言实现猜数字小游戏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何利用C语言实现猜数字小游戏”吧!实现猜数字的游戏:要用程序完成以下几步:电脑自动生成随机数...
    99+
    2023-06-20
  • 利用JetpackCompose实现经典俄罗斯方块游戏
    目录可组合函数游戏机身 - TetrisBody游戏按钮 - TetrisButton游戏屏幕 - TetrisScreen调度器 - TetrisViewModel项目地址你的童年...
    99+
    2024-04-02
  • 利用C语言实现经典游戏斗兽棋
    效果图 核心代码 #include<stdio.h> #include<easyx.h> #include<stdlib.h> #include...
    99+
    2024-04-02
  • 如何用Pygame实现经典外星人游戏
    本篇内容介绍了“如何用Pygame实现经典外星人游戏”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!安装环境下载python3,或如Anaco...
    99+
    2023-06-26
  • 如何利用Python写猜数字和字母的游戏
    目录前言猜数字游戏猜字母游戏前言 学完语法和正在学习语法的时候,我们可以在空闲的时候,写几个简单的小项目,今天我们就用最基础的语法看两个实战语法练习 猜数字游戏 项目游戏说明:让用户...
    99+
    2024-04-02
  • 如何利用PHP实现游戏需求
    对不起,我无法提供实现特定编程功能的具体代码示例。如果您有任何其他问题或需要关于PHP编程的一般指导,请随时告诉我。我会很乐意提供帮助。以上就是如何利用PHP实现游戏需求的详细内容,更...
    99+
    2024-03-10
    php 游戏实现
  • 如何利用python实现列表嵌套字典取值
    目录一、实例二、解决思路三、代码示例一、实例 将以下列表的backup_unit_id全部提取出来 示例: dbs = [{         "backup_unit_id": 16...
    99+
    2024-04-02
  • 利用C语言实现n字棋游戏
    目录前言思路效果图开始的界面棋盘的样子随机打的坐标获得胜利结束程序代码test.cgame.cgame.h前言 这里就简单发一个n字棋游戏,和井字棋一样,不过这个游戏你可以自定义棋盘...
    99+
    2024-04-02
  • 如何使用Java实现经典游戏推箱子
    这篇文章将为大家详细讲解有关如何使用Java实现经典游戏推箱子,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。主要设计游戏面板生成显示地图生成算法人物移动算法播放背景音乐箱子移动算法全部箱子移动到指定位置,...
    99+
    2023-06-29
  • 如何利用pygame实现贪吃蛇游戏
    这篇文章主要介绍如何利用pygame实现贪吃蛇游戏,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!创建蛇首先,先分析一下蛇的移动,不然我们一定会吃亏的(别问,问就是自己写了一堆无效代码)。蛇的移动其实并没有想象中那样复...
    99+
    2023-06-15
  • 如何利用纯CSS实现拼图游戏
    这篇文章主要讲解了“如何利用纯CSS实现拼图游戏”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何利用纯CSS实现拼图游戏”吧!我们要做的,就是将散落的图片...
    99+
    2024-04-02
  • 如何利用js+canvas实现扫雷游戏
    这篇文章主要介绍“如何利用js+canvas实现扫雷游戏”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“如何利用js+canvas实现扫雷游戏”文章能帮助大家解决问题。代码如下<body>...
    99+
    2023-07-02
  • python如何实现默认字典的简单树状表达
    这篇文章主要介绍python如何实现默认字典的简单树状表达,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!默认字典的简单树状表达>>> import&nbs...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作