我如何计算 Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch 中的字母?

How do I count the letters in Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch?

如何计算 Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch 中的字母?

print(len('Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch'))

说 58

好吧,如果有那么简单我就不会问你了,现在我会吗?!

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

The long form of the name is the longest place name in the United Kingdom and one of the longest in the world at 58 characters (51 "letters" since "ch" and "ll" are digraphs, and are treated as single letters in the Welsh language).

所以我想算一下,得到答案 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 个 ll 并且取下了三个而不是两个。所以这将需要修复。 (不得重叠。)

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

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

所以 'Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch' 似乎是其中 -ng- 有点只是“字母并置”的词之一。

而且显然计算机无法知道这一点。所以我将不得不向它提供 Wikipedia 谈论的“附加信息”。

所以无论如何,我决定查看在线词典 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) - 再次计算 |

我该如何正确修复它?

  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))

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

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

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

>>> 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

字符 class [^\W\d_](来自 here)匹配非数字或下划线的 word-characters,即字母,包括带有变音符号的字母。

您可以使用组合字素连接符 (+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