用威尔士语对文本中的字母计数

问题描述

我如何计算Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch中的字母?

print(len('Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch'))

说58

好吧,如果我这么简单,我不会问你,现在好吗?!

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

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

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

Okey dokey。

print(len(['Ll','a','n','f','i','r','p','w','ll','g','y','o','e','ch','d','b','t','s','l','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','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个ll,从三个起飞而不是两个。因此,这将需要修复。 (不得重叠。)

然后还有另一个问题。 ng。 Wikipedia并没有说名字中有一个字母“ ng”,但是在我上面引用的页面上,它被列为有向图之一。

Wikipedia在这里为我们提供了更多线索:“可能需要其他信息才能区分真正的有向图和字母并列”。并给出了“ llongyfarch ”的示例,其中ng只是“字母的并置”,而“ llong ”是有向图。

因此,似乎'Llanfairpwllgwy ng yllgogerychwyrndrobwllllantysiliogogogoch'是其中-ng-只是“字母并置”的那些单词之一。

显然,计算机无法知道这一点。因此,我将不得不提供Wikipedia谈论的“其他信息”。

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

screenshot from dictionary (llongyfarch)

screenshot from dictionary (llong)

因此,我决定好了,我们需要做的是通过像在字典中那样在输入字符串中放置|来提供附加信息,只是为了使算法知道{{1} }位实际上是两个字母。但是显然我不希望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)

规则将是:

  1. 忽略大小写

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

  3. 从左到右工作,以使['ch','th'] llll + ll,而不是ll + l + {{1 }}

  4. 如果您看不到ll,但是您无法完全忽略它,它可以阻止l成为有向图

我希望它能算为51,并且出于正确的原因而做,而不仅仅是fl幸。

现在我得到51,但它是骗人的,因为它把|算作一个字母(1太高了),然后它与ng(1太低)-错误取消

它使|正确(3)。

出现llll错误(10)-重新计算llong

如何正确解决问题?

解决方法

与字符串有关的许多问题一样,可以使用正则表达式以简单的方式完成。

this.ObsA

字符类{'a': ['a1','a2','a3'],'b': ['b1','b2'],'c': [1,2,3,4,5]} (来自here)匹配不是数字或下划线的单词字符,即字母,包括带有变音符号的字母。

,

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

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. 逐个字母地浏览字符串
  2. 如果您在索引n处并且s [n:n + 2]是一个有向图,则以该有向图为键添加或增加一个字典,并将索引也增加1,这样您就不会开始于第二个有向图字符。如果它不是有向图,则只需将字母添加或增加到字典,然后转到下一个字母即可。
  3. 如果看到|字符,不要算,只需跳过。
  4. 别忘了小写。

看到所有字母后,循环结束,并将所有计数添加到字典中。

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

from collections import defaultdict

digraphs=['ch','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))
,

您可以使用组合音素连接符(+ u034F)来连接字母,然后计算字符数并取走这些连接符的数量* 2。

http://www.comisiynyddygymraeg.cymru/English/Part%203/10%20Locales%20alphabets%20and%20character%20sets/10.2%20Alphabets/Pages/10-2-4-Combining-Grapheme-Joiner.aspx

威尔士语言专员也在这里解决此问题: http://www.comisiynyddygymraeg.cymru/English/Part%203/10%20Locales%20alphabets%20and%20character%20sets/10.2%20Alphabets/Pages/10-2-1-Character-vs--letter-counts.aspx

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...