Python 如何从字典中建立一个比暴力更好的单词板?
考虑以下字母排列:Python 如何从字典中建立一个比暴力更好的单词板?,python,algorithm,Python,Algorithm,考虑以下字母排列: B O A N R I D E N T 从上面的字母开始,从下面的两个字母中选择一个,Plinko样式,直到到达底部。无论你选择哪条路,你都会创造一个四个字母的单词:邦德、骨头、无聊、出生、裸露、谷仓、贝恩或诱饵。事实上,登特在底部的读数只是一个很好的巧合 我想帮助找出一个算法,可以设计这样一个布局,其中从上到下的每个可能路径从(提供的)字典生成一个不同的单词。程序的输入将是起始字母(本例中为B)和字长n(本例中为4)。它会返回组成这样一个布局的字母,或
B
O A
N R I
D E N T
从上面的字母开始,从下面的两个字母中选择一个,Plinko样式,直到到达底部。无论你选择哪条路,你都会创造一个四个字母的单词:邦德、骨头、无聊、出生、裸露、谷仓、贝恩或诱饵。事实上,登特在底部的读数只是一个很好的巧合
我想帮助找出一个算法,可以设计这样一个布局,其中从上到下的每个可能路径从(提供的)字典生成一个不同的单词。程序的输入将是起始字母(本例中为B)和字长n(本例中为4)。它会返回组成这样一个布局的字母,或者一条消息说这是不可能的。它不必是确定性的,因此它可以用相同的输入生成不同的布局
到目前为止,我还没有想到比暴力手段更好的方法。也就是说,对于所有为布局底部选择字母的
26^[(n+2)(n-1)/2]
方法,检查所有可能的2^(n-1)
路径是否都给出字典中的单词。我考虑过某种前缀树,但路径可以交叉并共享字母这一事实让我感到困惑。我对Python非常熟悉,但至少我希望有一种算法或方法可以解决这个问题。谢谢 假设底部的V W X Y Z
实际上完成了单词
B
A O
I R N
T N E D
V W X Y Z
我们可以使用非常严格的启发式实现回溯搜索,似乎任何错误的路径都不会走得太远
在一个简单的树中插入所有以相同字母开头的n
大小的单词,如下所示。现在执行深度优先搜索,断言以下内容:每个连续级别需要一个额外的“共享”字母,这意味着该级别上的p(字母)
实例,另外还要求其两个子级是相同的字母(例如,级别2括号中的两个R
s可以是“共享的”因为他们的孩子是一样的)
什么是p(字母)
?当然是帕斯卡三角形n choose r
是根据Plinko board,在这个简单树的相关级别上所需的字母实例数。在第三级,如果我们选择了R
和R
,我们需要3个N
s和3个E
s来表示该级别上的“共享”字母。3个N
s中的每一个都必须有相同的子字母(在本例中为W,X),3个E
s中的每一个也必须有(X,Y)
更新
出于好奇,这里有一些:)
来自itertools导入组合的
从复制导入deepcopy
#假设所有的话都开始了
#用同样的字母和
#长度相同
def插入(字、i、树):
如果i==len(单词):
返回
如果树中有单词[i]:
插入(word,i+1,树[word[i]])
其他:
树[word[i]={}
插入(word,i+1,树[word[i]])
#帕斯卡三角形
def get_next_需要(需要):
next_needed=[[1,无,0]+[None]*(len(needed)-1)+[[1,无,0]]
对于i,u在枚举中(需要):
如果i==len(需要)-1:
下一步需要[i+1]=[1,无,0]
其他:
下一个_needed[i+1]=[needed[i][0]+needed[i+1][0],无,0]
需要时返回下一个
def get_候选人(下一个需要、选中、家长):
全局日志
如果记录:
打印“获取候选项:父项:%s”%parents
#对于每个选择的节点,我们需要两个子节点。
#角点只有一个共享节点,而
#每组中的其他人都是相同的
#必须有一对完全相同的孩子
#给小组中的其他人。此外
#共享序列在每个组的末尾匹配。
#I(R)(R)N
# / \ / \ / \ / \
#T(N)(N)E(N)E D
#迭代父对象,选择
#每个节点有两个节点
定义g(cs、s、序列、i、h):
如果记录:
打印“cs,seq,s,i,h:%s,%s,%s,%s,%s”%(cs,s,seq,i,h)
#基本情况下,我们得到了一个候选序列
如果i==len(父母):
返回[(cs,s,seq)]
#角落里的左边字符是
#武断的;下一个,共享。
#左上角:
如果i==0:
候选人=[]
对于组合中的(l,r)(选择[0]。键(),2):
_cs=深度复制(cs)
_cs[0]=[1,l,1]
_cs[1][1]=r
_cs[1][2]=1
_s=s[:]
_s、 扩展([选择的[0][l],选择的[0][r]])
_h=深度复制(h)
#将索引保存在
#为父节点选择的节点
_h[父母[1]]=[1,2]
扩展(g(_-cs,_-s,l+r,1,_-h))
_cs=深度复制(cs)
_cs[0]=[1,r,1]
_cs[1][1]=l
_cs[1][2]=1
_s=s[:]
_s、 扩展([选择的[0][r],选择的[0][l]])
_h=深度复制(h)
#将索引保存在
#为父节点选择的节点
_h[父母[1]]=[1,2]
扩展(g(_-cs,_-s,r+l,1,_-h))
如果记录:
打印“正在返回的候选人:%s”%s
返回候选人
#正确的字符是任意的,但是
#前一个字符必须与前一个字符匹配。
如果i==len(父母)-1:
l=cs[len(cs)-2][1]
如果记录:
打印“最右边的字符:%s”%l
如果len(selected[i])<2或(selected[i]中没有l):
如果记录:
打印“未找到匹配项:len(所选[i])<2或(所选[i]中没有l])”
返回[]
其他:
结果=[]
对于[x]中的r,对于所选[i]中的x,如果x!=l],则为keys():
_cs=深度复制(cs)
_cs[len(cs)-2][2]=_cs[len(cs)-2][2]+1
_cs[len(cs)-1]=[1,r,1]
_s=s[:]+[选择的[i][l],选择的[i][r]]
结果.追加((_cs,_s,seq+l+r))
返回结果
父母=父母[i]
如果记录:
打印“获取候选项:g:父项,i:%s,%s”%(pa
B
/ \
A O
/ \ / \
I (R) (R) N
/ \ / \ / \ / \
T (N) (N) E (N) E E D
V W W X W X X Y W X X Y X Y Y Z
4 W's, 6 X's, 4 Y's
b
a u
l n r
l d g s
o y s a e
b
a ?
l ? ?
l ? ? ?
o ? ? ? ?
b
a u
l ? r
l ? ? k
o ? ? ? e