【问题标题】:how can i make this code that lets computer to choose word from wordList of 83667 words fastly?我怎样才能制作让计算机从 83667 个单词的 wordList 中快速选择单词的代码?
【发布时间】:2017-02-21 11:08:51
【问题描述】:

提供 compChooseWord(hand, wordList, n) 函数的更快版本。 这里有一些细节。

wordList 是 83667 个单词的列表;

手是 {'a': 1, 'p': 2, 's': 1, 'e': 1, 'l': 1}

n 为正整数

SCRABBLE_LETTER_VALUES = {
    'a': 1, 'b': 3, 'c': 3, 'd': 2, 'e': 1, 'f': 4, 'g': 2, 'h': 4, 'i': 1, 'j': 8, 'k': 5, 'l': 1, 'm': 3, 'n': 1, 'o': 1, 'p': 3, 'q': 10, 'r': 1, 's': 1, 't': 1, 'u': 1, 'v': 4, 'w': 4, 'x': 8, 'y': 4, 'z': 10
}

def getWordScore(word, n):

    score=0
    for i in word:
       if i in SCRABBLE_LETTER_VALUES:
           score=score+SCRABBLE_LETTER_VALUES[i]
    score=score*len(word)

    if len(word)==n:
       score=score+50

    return score
def isValidWord(word, hand, wordList):

    """
    Returns True if word is in the wordList and is entirely
    composed of letters in the hand. Otherwise, returns False.

    Does not mutate hand or wordList.

    word: string
    hand: dictionary (string -> int)
    wordList: list of lowercase strings
    """


    c=True
    wordCount=len(word)
    handCopy=hand.copy()
    for i in word:
         if i in hand:
            handCopy[i]=handCopy.get(i,0)-1
            wordCount=wordCount-1
            if handCopy[i]<0:
              c=False
              break

    b=word in wordList and wordCount==0

    return  b and c

为以下功能提供替代更快的版本

def compChooseWord(hand, wordList, n):

    """
    Given a hand and a wordList, find the word that gives 
    the maximum value score, and return it.

    This word should be calculated by considering all the words
    in the wordList.

    If no words in the wordList can be made from the hand, return None.

    hand: dictionary (string -> int)
    wordList: list (string)
    n: integer (HAND_SIZE; i.e., hand size required for additional points)

    returns: string or None
    """

    bestScore = 0
    bestWord = None
    for word in wordList:
        if isValidWord(word, hand, wordList):
            score = getWordScore(word, n)
            if (score > bestScore):
                bestScore = score
                bestWord = word
    return bestWord

【问题讨论】:

  • 这听起来像是家庭作业...这是家庭作业吗?你有什么尝试让它更快,结果是什么?目前的表现有多差?
  • 一个简单的事情就是按分数对 wodlist 进行排序。这样一来,您就可以在找到有效单词后立即停止循环。

标签: performance function python-3.x loops data-structures


【解决方案1】:

根据上面的@mroman 评论:最简单的优化就是将wordist 排序在反向分值中,并在找到第一个单词时停止。

Python 排序对这样的事情非常有效,因为它允许函数 getWordScoreitsef 用作排序的键,它甚至可以在排序时考虑你的手的大小 - 所以你的搜索会是:

def compChooseWord(hand, wordList, n):

    bestScore = 0
    bestWord = None
    wordList = sorted(wordList, key=lambda word: getWordScore(word, n))
    for word in wordList:
        if isValidWord(word, hand, wordList):
            break
    else:
         # No "break" means: end of the list with no word-matching
         return None
    return word

但是,如果这还不够,您还可以重写isValidWord 以更快一点,首先使用“set”验证一个人是否确实具有组成单词所需的字母,然后只需 fif因此,请使用更昂贵的字母计数检查方法来验证字母计数:

def isValidWord(word, hand, wordList):

    word_letters = set(word)
    if not word_letters.intersection(hand.keys()):
         # You don't have the needed letters to start with
         return False
    handCopy=hand.copy()

    for letter in word:
        handCopy[letter] -= 1
        if handCopy[letter] < 0:
            return False              

    return wordCount == 0

请注意,如果您在“单词”中循环遍历“字母”,则没有 将它们命名为“i”的理由 - 只需称它们为“字母”。第二件事:你不需要太多的辅助变量,比如'wordCount':当循环结束时,你会检查所有的字母。而且,只返回 False,而不是设置一个辅助(并且命名错误)b 变量来指示匹配仍然失败

另外:您可以使用增强的赋值运算符-= 来避免在等式两边重复表达式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    相关资源
    最近更新 更多