【问题标题】:How do I count the letters in Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch?如何计算 Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch 中的字母?
【发布时间】:2020-12-11 04:34:33
【问题描述】:

如何计算 Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch 中的字母?

print(len('Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch'))

说 58

如果这么简单,我就不会问你了,现在可以吗?!

维基百科说 (https://en.wikipedia.org/wiki/Llanfairpwllgwyngyll#Placename_and_toponymy)

名字的长形式是美国最长的地名 王国和世界上最长的王国之一,有 58 个字符 (51 "letters" 因为 "ch" 和 "ll" 是有向图,并被视为单个 威尔士语字母)。

所以我想数一下,得到答案 51。

好啊。

print(len(['Ll','a','n','f','a','i','r','p','w','ll','g','w','y','n','g','y','ll','g','o','g','e','r','y','ch','w','y','r','n','d','r','o','b','w','ll','ll','a','n','t','y','s','i','l','i','o','g','o','g','o','g','o','ch']))
51

是的,但那是作弊,显然我想使用单词作为输入,而不是列表。

维基百科还说威尔士语的二合字母是ch, dd, ff, ng, ll, ph, rh, th

https://en.wikipedia.org/wiki/Welsh_orthography#Digraphs

所以我们走吧。让我们把长度加起来,然后去掉重复计算。

word='Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch'
count=len(word)
print('starting with count of',count)
for index in range(len(word)-1):
  substring=word[index]+word[index+1]
  if substring.lower() in ['ch','dd','ff','ng','ll','ph','rh','th']:
    print('taking off double counting of',substring)
    count=count-1
print(count)

这让我走到了这一步

starting with count of 58
taking off double counting of Ll
taking off double counting of ll
taking off double counting of ng
taking off double counting of ll
taking off double counting of ch
taking off double counting of ll
taking off double counting of ll
taking off double counting of ll
taking off double counting of ch
49

看来我已经减去了太多。我应该得到 51。现在的一个问题是,llll 找到了 3 个lls,并且删除了三个而不是两个。所以这需要修复。 (不得重叠。)

然后还有另一个问题。 ng。维基百科没有说名字中有一个字母“ng”,但它被列为我上面引用的页面上的二合字母之一。

维基百科在这里为我们提供了更多线索:“可能需要额外的信息来区分真正的二合字母和并列的字母”。它给出了“llongyfarch”的例子,其中 ng 只是“字母的并置”,而“llong”则是一个有向图。

因此,'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch' 似乎是其中一个 -ng- 只是“字母并置”的词之一。

显然计算机不可能知道这一点。所以我将不得不给它提供维基百科所说的“附加信息”。

所以无论如何,我决定查看在线词典http://geiriadur.ac.uk/gpc/gpc.html,如果您查找 llongyfarch(维基百科中的“字母并列”示例),它会显示在 n 和 g 之间有一条垂直线,但如果您查找“llong”,则它不会这样做。

所以我已经决定好了,我们需要做的是通过在输入字符串中像在字典中一样输入 | 来提供附加信息,以便算法知道 ng 位确实是两个字母。但显然我不希望 | 本身被算作一个字母。

所以现在我有这些输入:

word='llong'
ANSWER NEEDS TO BE 3 (ll o ng)

word='llon|gyfarch'
ANSWER NEEDS TO BE 9 (ll o n g y f a r ch)

word='Llanfairpwllgwyn|gyllgogerychwyrndrobwllllantysiliogogogoch'
ANSWER NEEDS TO BE 51 (Ll a n f a i r p w ll g w y n g y ll g o g e r y ch w y r n d r o b w ll ll a n t y s i l i o g o g o g o ch)

还有这个二合字母列表:

['ch','dd','ff','ng','ll','ph','rh','th']

规则如下:

  1. 忽略大小写

  2. 如果您看到一个有向图,则将其计为 1

  3. 从左到右工作,使llllll + ll,而不是l + ll + l

  4. 如果您看到 | 不计其数,但您不能完全忽略它,它可以阻止 ng 成为有向图

我希望它算作 51 并出于正确的理由这样做,而不仅仅是侥幸。

现在我得到 51,但它是侥幸,因为它把 | 算作一个字母(1 太高),然后它用 llll 起飞太多了(1 太低) -错误取消

llong 正确 (3)。

llon|gyfarch 错误 (10) - 再次计算 |

我怎样才能以正确的方式解决它?

【问题讨论】:

  • 既然您尝试测量的只是一个单词并且您知道该单词及其长度,为什么不创建一个常量字符串来包含该字符串,并创建一个常量 int 来包含字符串并完成它?不需要在代码中这样做,对吧?
  • 我对python了解不多。完成count=count-1 之后,可以添加index=index+1 跳过下一个字母吗?
  • 所以我对python不太了解,但我认为他们必须对字符串有一些文化概念?例如,在 .NET 中,您可以设置应用程序的文化,并以此为基础对某些字符进行不同的处理。除非这里的想法是您尝试自己从头开始实施,否则请忽略此评论。
  • 如果是 C#,我可以提供 "ch dd ff ng ll ph rh th |".Split().ToList().ForEach(a => sb.Replace(a, a == "|" ? ".": "")); //sb is a stringbuilder - 只需将每个二合字母替换为字符串中未出现的字符,最后将 | 替换为空;结果长度是你的字符串。不是 python 开发人员,但应该使用相同的过程,用单个替换双打..
  • "th" 和 "sh" 是英语中的二合字母,但我从来没有遇到过从字形意义上考虑这些“单个字母”的人。您问的是如何计算“phonemes”,它以笨拙地映射到用字母书写的语言而臭名昭著。您已经确定的音节中断只是一种歧义。

标签: python counting letter


【解决方案1】:

【讨论】:

    【解决方案2】:

    就像许多与字符串有关的问题一样,这可以通过正则表达式以简单的方式完成。

    >>> word = 'Llanfairpwllgwyn|gyllgogerychwyrndrobwllllantysiliogogogoch'
    >>> import re
    >>> pattern = re.compile(r'ch|dd|ff|ng|ll|ph|rh|th|[^\W\d_]', flags=re.IGNORECASE)
    >>> len(pattern.findall(word))
    51
    

    字符类[^\W\d_](来自here)匹配不是数字或下划线的单词字符,即字母,包括带有变音符号的字符。

    【讨论】:

    • 那里的条件顺序重要吗?因为它首先出现,所以会优先于 a 到 z 吗?更具体地说,是正则表达式特定的东西还是每种语言都有自己的实现?
    • 如果你想让正则表达式处理原始输入:pattern = re.compile(r'ch|dd|ff|ll|ph|rh|th|[a-z]|(ng^yf)', flags=re.IGNORECASE)
    • @MaxYoung 是的,部分的顺序就是为什么二合字母优先于单个字母;在我见过的每个正则表达式引擎中,这通常都是正确的。具体来说,在 Python 中,the docs"当目标字符串被扫描时,RE 被 '|' 分隔从左到右尝试”,因此它是指定的行为并且可以安全依赖。
    • 然后是威尔士语使用来自英语的几个借词/短语并且并不总是将它们的拼写更改为威尔士拼写的问题,因此您不能绝对指望有向图是有向图...: -|啊,自然语言真是有趣。 :-)
    • @benjessop,(ng^yf) 是关于什么的?当^ 表示字符串的开头时,它可以匹配任何东西吗?
    【解决方案3】:
    1. 一个字母一个字母地遍历字符串
    2. 如果您在索引 n 并且 s[n:n+2] 是一个有向图,则添加或增加一个以有向图为键的字典,并将索引也增加 1,这样您就不会开始第二个二合字母。如果不是有向图,只需将字母添加或递增到字典并转到下一个字母。
    3. 如果您看到 |字符,不计其数,跳过。
    4. 别忘了小写。

    当你看到所有的字母时,循环结束,你将所有的计数添加到字典中。

    这是我的代码,它适用于您的三个示例:

    from collections import defaultdict
    
    digraphs=['ch','dd','ff','ng','ll','ph','rh','th']
    breakchars=['|']
    
    
    def welshcount(word):
        word = word.lower()
        index = 0
        counts = defaultdict(int)  # keys start at 0 if not already present
        while index < len(word):
            if word[index:index+2] in digraphs:
                counts[word[index:index+2]] += 1
                index += 1
            elif word[index] in breakchars:
                pass  # in case you want to do something here later
            else:  # plain old letter
                counts[word[index]] += 1
    
            index += 1
    
        return sum(counts.values())
    
    word1='llong'
    #ANSWER NEEDS TO BE 3 (ll o ng)
    
    word2='llon|gyfarch'
    #ANSWER NEEDS TO BE 9 (ll o n g y f a r ch)
    
    word3='Llanfairpwllgwyn|gyllgogerychwyrndrobwllllantysiliogogogoch'
    #ANSWER NEEDS TO BE 51 (Ll a n f a i r p w ll g w y n g y ll g o g e r y ch w y r n d r o b w ll ll a n t y s i l i o g o g o g o ch)
    
    print(welshcount(word1))
    print(welshcount(word2))
    print(welshcount(word3))
    

    【讨论】:

      【解决方案4】:

      您可以通过将所有双字母替换为.(或任何其他字符,? 就可以了)并测量结果字符串的长度(减去 | 的数量)来获得长度):

      def get_length(name):
          name = name.lower()
          doubles = ['ch', 'dd', 'ff', 'ng', 'll', 'ph', 'rh', 'th']
          for double in doubles:
              name = name.replace(double, '.')
          return len(name) - name.count('|')
      
      name = 'Llanfairpwllgwyn|gyllgogerychwyrndrobwllllantysiliogogogoch'
      print(get_length(name))
      >>> 51
      

      【讨论】:

      • +1 非常简单,我从没想过仅仅为了缺乏更好的术语而对共轭的字符进行标记。我有一种感觉,我必须将其应用于我一直在研究的用于检测日语文本中重复字符但重复正确的算法。我在日语中遇到的问题是,例如 haha​​ha 将是三个背靠背的相同字符,但理论上这可能是我说的前两个字符,最后一个字符是助词。
      • 在这种情况下可以正常工作。如果将此方法应用于其他字符串,则需要确保中间变量不包含原始字符串中不存在的二合字母。
      猜你喜欢
      • 2018-11-11
      • 2019-12-28
      • 2019-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-21
      • 2018-10-25
      相关资源
      最近更新 更多