我有一个名为Quiddler的纸牌游戏,我正在尝试编写一个算法来解决,但是当我尝试线性地解决它时它非常慢且效率低。
游戏(循序渐进):
虽然我尽力使用算法来完成这些看似简单的任务,但即使是中长手也需要20秒才能找到所有答案。
我使用字典such as this one作为我的单词列表。我线性检查手中的字母数量,并将其与列表中的字词进行比较,假设它们的长度相等或更短。虽然这项工作需要很长时间。
我希望有人可以帮助我,最好是Perl,Python或C / C ++。
示例手: 卡= [ 'I', 'd', '0', 'N']
答案(根据我的算法): 迪不, 迪, 做, 证件号码, id on, 在做, 在外面, 恐龙, nodi
import timeit
from wordlist import *
#Quiddler Solver
print 'Dictionary loaded\n'
#Define our hand
cards=['i','d','o','n']
#Count the letters in a word
def cntLetters(word): #Surely there's a better way?
lettercnt={97:0,98:0,99:0,100:0,101:0,102:0,103:0,104:0,105:0,106:0,107:0,108:0,109:0,110:0,111:0,112:0,113:0,114:0,115:0,116:0,117:0,118:0,119:0,120:0,121:0,122:0}
for v in word:
lettercnt[ord(v)]+=1
return lettercnt
#Check the letters to make sure our hand has at least what the word has
def cmpList(list1,list2):
for k,v in list1.iteritems():
if list2[k]<=v:
pass
else:
return False
return True
#Check to make sure cards with more than one letter are together in the word.
def has(word):
for v in cards:
if len(v)>1:
if v in word:
pass
else:
return False
return True
def solve():
rawhand=''.join(cards).lower()
hand=cntLetters(rawhand)
handl=len(rawhand)
buff=[]
for v in dict: #Add all words that have at least the letters in our hand to buff
if len(v)<=handl and cmpList(hand,cntLetters(v)):
if has(v):
buff.append(v)
for v in range(0,int((len(buff)/2)+1)): #Find 2 words that can be used together to make a play
for n in buff:
if len(n)==(handl-len(buff[v])):
if hand==cntLetters(buff[v]+n):
print buff[v],n
for v in range(0,int((len(buff)/3)+1)): #This is a bit overkill since it finds so much stuff, need to tune it
for n in buff:
if (len(n))<=len(buff[v]):
for x in buff:
if len(x)==(handl-len(buff[v])-len(n)):
if hand==cntLetters(buff[v]+n+x):
print buff[v],n,x
for v in buff: #Print the single words that can be made
if len(v)==handl:
print v
t = timeit.Timer(stmt=solve)
print 'Search took %.2f seconds'%t.timeit(number=1)
我从wordlist导入一个名为dict的预编译列表。
我希望有人可以帮我解决我的算法设计,因为它需要改进,谢谢。
有人建议使用DAWG,但我没有进行任何单词查找。在这种情况下,我仍然需要循环检查字母,除非我在想错误的行?
答案 0 :(得分:4)
您可以尝试将单词列表存储为directed acyclic word graph(DAWG)或trie以进行快速查找。
放置第一个字母并使用DAWG / trie找出第二个字母的所有可能性,依此类推。当没有更多的字母可以放置,或者找到解决方案而你想要下一个字母时,请使用回溯。
此算法应该在解决方案的数量上大致呈线性,如果有效写入应该能够在几毫秒内为10张卡解决您的问题。请注意,随着您添加更多卡片,解决方案的数量会迅速增长。
答案 1 :(得分:1)
从您的问题到设置封面有一个非常简单的减少,这是NP完全的,所以虽然您可以使用DAWG进行微小的改进,但是没有已知的有效解决方案。