【问题标题】:Check if a word can be made from a group of letters (considering the no. of times the letters can be used)?检查是否可以由一组字母组成一个单词(考虑字母可以使用的次数)?
【发布时间】:2015-07-28 17:57:55
【问题描述】:

我正在做一个文本扭曲程序,但在检查是否可以从给定的字母组中创建一个单词时遇到问题。如果没有重复的字母,这很容易,但是如果用户输入了一个有重复字母的单词,我该怎么办?我使用了元组,但如果字母重复,它就不起作用了。

为了更清楚,我提供了这个例子:

假设您的字母组是(d,n,a,e,l,i),用户输入单词need。我们可以看到字母 e 在这里被使用了两次,但是由于我编写的代码(使用元组)只是检查列表是否是列表的子集,所以当它不是时,它会将 need 视为正确答案.我如何解决它?

【问题讨论】:

  • 请提供您已经尝试过的示例。
  • 您需要检查组中是否包含必要的单词,以及每个字母出现的次数是否足够。
  • 贴一些更有效和无效的例子。
  • edit您的问题并发布您的程序内容。如果我们不知道您在做什么,我们将无法帮助您。
  • 这是一个基于迄今为止提供的信息的相关问题:stackoverflow.com/questions/15208369/…

标签: python list python-3.x subset multiset


【解决方案1】:

一种方式,使用collections.Counter

from collections import Counter
bag = Counter('dnaeli')
>>> Counter({'a': 1, 'e': 1, 'd': 1, 'i': 1, 'l': 1, 'n': 1})

bag.subtract(Counter('need'))
>>> Counter({'a': 1, 'i': 1, 'l': 1, 'd': 0, 'n': 0, 'e': -1})

if all(v >= 0 for v in bag.values()):
    print 'Word is contained'

# or as a three-line function:
def is_contained(a, b):
    """Test if all the letters of word a are contained in word b"""
    letters = Counter(b)
    letters.subtract(Counter(a))
    return all(v >= 0 for v in letters.values())

注意:Counter.subtract() 不同于- 操作,即Counter.__sub__()Counter.subtract() 也会传播负数(和零),这是您需要检查的内容 [¹]。

([¹] @StefanPochmann 的方法从候选词中减去字母;我的方法相反。在 SP 的情况下,正剩余计数不好;在我的情况下,负数不好。所以他的方法不需要关心负数或零计数,但我的计数。他的不太复杂,因此更好。)

【讨论】:

    【解决方案2】:

    您可以尝试从允许列表中删除每个字母,直到您完成或出现问题(意味着您无法构造该单词):

    def TestInput(user_input_string, avia_letters_list):
        for each_letter in user_input_string:
            try:
                avia_letters_list.remove(each_letter)
            except ValueError:
                return 'sorry "%s" can not be constructed' % user_input_string  
        return 'good job, "%s" can be constructed' % user_input_string
    
    usable_letters = ['d', 'n', 'a', 'e', 'l', 'i']
    
    print TestInput('need', usable_letters[:])
    print TestInput('lid', usable_letters[:])
    print TestInput('nail', usable_letters[:])
    

    输出:

    sorry "need" can not be constructed
    good job, "lid" can be constructed
    good job, "nail" can be constructed
    

    【讨论】:

      【解决方案3】:

      是的,集合不起作用,但多集合可以。 Counter 可以用于此。

      letters = 'dnaeli'
      words = 'line', 'linda', 'need', 'den', 'x'
      
      from collections import Counter
      for word in words:
          if not Counter(word) - Counter(letters):
              print(word)
      

      打印:

      line
      linda
      den
      

      或者:

      for word in words:
          if all(letters.count(c) >= word.count(c) for c in word):
              print(word)
      

      如果你的字母集都很大并且你的单词很长,这会很慢,但是“正常使用”没关系。

      【讨论】:

      • 注意:Counter.subtract() 不同于- 操作,即Counter.__sub__()Counter.subtract() 也会传播负数和零计数
      • 好吧,我没有使用subtract,所以我不明白你为什么这么说。
      • 嗯。您的方法从候选词中减去字母;我的正好相反。在您的情况下,剩余的正数是不好的;在我的负面是坏的。所以,是的,你的方法不需要关心负数或零计数,但我的方法需要。很有趣。
      • 说实话我不知道subtract 是做什么的;我不确定我曾经使用过它。或者也许我做了,然后不喜欢它,再也没有回头:-)
      • 我也不是 :-) 我只知道内置集合操作必须对Counters 采取“不同”行为才能获得“正确”结果。现在我们知道了。
      猜你喜欢
      • 1970-01-01
      • 2020-02-07
      • 2015-03-28
      • 2014-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-04
      • 1970-01-01
      相关资源
      最近更新 更多