【问题标题】:Python RegEx- hangman algorithmPython RegEx-hangman 算法
【发布时间】:2011-09-14 10:22:00
【问题描述】:

我正在尝试编写一个刽子手算法。我的想法是这样的:

  • 预处理包含单词的相对字母频率的字典,具体取决于单词的长度。步骤完成。

例子:

#Each key corresponds to length of the word.   

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

我还有一个字典中的单词生成器:

dictionary = word_reader('C:\\Python27\\dictionary.txt', len(letters))

基于这个函数

#Strips dictionary of words that are too big or too small from the list
def word_reader(filename, L):
  L2 = L+2
  return (word.strip() for word in open(filename) \
          if len(word) < L2 and len(word) > 2)
  • 这个特殊的游戏将免费为您提供最后一个元音。例如,如果这个词是土的, 用户将获得以下棋盘:e----e- 进行猜测。所以,我想找到一种方法来创建一个新的生成器或列表 去掉所有不符合 e----e- 模板的词。

p = re.compile('^e\D\D\D\De\D$', re.IGNORECASE) 会这样做,但它可能会找到单词 除了第一个字母和倒数第二个字母之外的其他地方包含“e”。

所以我的第一个问题是:

  1. 如何确保“e”是 仅位于第一个和 倒数第二个位置
  2. 如何创建一个智能函数,该函数将在谜题更新和计算机不断猜测时具有新的正则表达式?

例如,如果单词是猴子,则计算机将只给出----e- 第一步是它从字典中删除所有不是 6 个字母的单词,以及所有不完全符合“----e-”模板的单词,并将其放入一个 newList 中。 怎么做 我要这样做吗?

然后它会根据其中单词的相对频率计算一个新的频率字典 新列表。

我目前的做法是这样的:

   cnt = Counter()
   for words in dictionary:
      for letters in words:
         cnt[letters]+=1

这是最有效的方法吗?

然后它会使用 newfrequencyDict 来猜测最常见的字母,假设它有 还没被猜到。它会继续这样做,直到(希望)猜到这个词。

这是一种有效的算法吗?有更好的实现吗?

【问题讨论】:

  • 这听起来像是一个刽子手求解程序而不是刽子手程序。

标签: python regex algorithm dictionary


【解决方案1】:

正则表达式没有什么特别神奇的地方,将它们与整个字典进行匹配仍然需要 O(n) 时间。我建议您编写自己的函数来确定一个单词是否与模板匹配,并通过它运行您的字典。

这是一个示例函数:

def matches_template(word, template):
  found_chars = set(x for x in template if x != '-')
  for char, template_char in zip(word, template):
    if template_char == '-':
      if char in found_chars: return False
    else:
      if template_char != char: return False
  return True

就确定下一个要猜测的字符而言,您可能不想选择最频繁出现的字符。相反,您想选择最接近 50% 单词的字符,这意味着您消除了大多数可能性。即使这样也不是最优的 - 可能是某些字符更有可能在单词中出现两次,因此消除了更大比例的候选 - 但它更接近。

【讨论】:

  • 最好选择最有可能的字符还是选择将剩余部分分成两半的字符,这取决于规则。如果猜对了,第一个相关的策略会给玩家一个额外的免费猜测。第二种策略有利于尽快确定正确的单词,即使是其他玩家之一获胜。
  • @Midtiby——你说得对,游戏就是这样工作的。但是,尼克——你提出了一个很好的观点。您将如何找到最接近 50% 单词的字符?
  • @Parseltongue 统计每个字符出现的字数,每次计数减去剩余字数的一半,选出绝对值最小的。
  • 谢谢。我最终将此作为我问题的正确答案,因为该功能完美运行。我只是对它的工作原理感到困惑。你介意解释一下吗?
  • @Parseltongue 它以同步的方式迭代候选词和“模板”。对于每个字符,如果模板包含'-'(例如,我们不知道它是什么),它会验证单词中的字符不是已经发现的字符。如果模板字符是其他字符,它会验证它是否与单词中的字符匹配。为了匹配,每一个检查都必须通过。
【解决方案2】:

这是相当多的问题。我会试着回答几个。

  1. 您的正则表达式应该看起来更像这样:'^e[^e][^e][^e][^e]e[^e]$'。那些[^e] 位说“匹配任何不是'e'的字符。请注意,与你的正则表达式不同,这个处理非字母字符,但如果你确保这应该不是问题您的字典只有字母。请注意,一旦您发现了多个字母,您会将所有字母放入每个“不匹配”部分。例如,假设“a”是猜测的,所以它是“ ea---e-",现在您将匹配正则表达式'^ea[^ae][^ae][^ae]e[^ae]$'。
  2. 您可以简单地编写一个函数,该函数接受诸如“ea---e-”之类的字符串并从中构建一个正则表达式。它只需要 a) 将字符串中的所有非连字符字母作为一个集合(在本例中为 {'a', 'e'}),b) 将集合展平为“匹配所有但这个”正则表达式片段([^ae]) -- 请注意,顺序并不重要,这就是我使用集合的原因,c) 用其中一个 (ea[^ae][^ae][^ae]e[^ae]) 替换每个连字符,并且 d) 最后只需将“^”放在最前面,最后是“$”。
  3. 最后是频率字典——这是一个非常独立的问题。很难比在整个字典中进行线性搜索更有效。我会提出的一个建议是,您可能不应该多次数字母。例如,您是否希望单词“earthen”对“e”的字母计数贡献 2 分?我猜在 Hangman 中你只希望它计数一次,因为单词“eeeeeeee”和单词“the”对于猜测字母“e”(成功)具有相同的结果。但我可能是错的。

【讨论】:

  • 数字 3 提出了一个有趣的观点——我如何防止它重复计算,这会对算法的获胜效果产生不利影响吗?至于 2,示例函数会是什么样子?我很难想象一个功能性正则表达式。
  • 如果你想防止它重复计算,你可以简单地将单词放入一个集合中。 set("earthen")set(['a', 'e', 'h', 'n', 'r', 't'])。然后使用集合中的每个字母来计算频率。我不知道您所说的“示例函数”或“功能正则表达式”是什么意思。我的字面意思是你会编写一个函数build_regex_matching("ea---e-"),它使用上面给出的算法返回"^ea[^ae][^ae][^ae]e[^ae]$"
猜你喜欢
  • 1970-01-01
  • 2018-10-16
  • 2021-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-17
  • 2016-05-28
相关资源
最近更新 更多