如何计算单词中的音节


22

输入:将为您传递一个包含单个英语单词的字符串。所有字母均为小写,并且字符串中没有非字母字符。

输出:您将返回一个从1到7的整数,表示您认为单词中有多少个音节。

评分:您的程序将针对此存储库中找到的所有单词运行。如果您输入的N单词正确,并且程序的大小为M字节,则分数为N-(M*10)。最高分获胜。

为了生成音节计数,我将用作单词列表,并以此对音节进行计数。


3个音节词包含“客栈”和“红宝石”。2个音节词包含以下内容:“ irs”,“ ore”,“ roy”,“ yer”。除此之外,列表似乎足够准确。
2015年

@justhalf谢谢你的收获。创建列表绝对是挑战中最困难的部分。
弥敦道·美林


3
这个挑战使我意识到英语是多么愚蠢。就拿resume例如...
SP3000

Answers:


12

Ruby,8618正确(91.1%),53字节,8618-10 * 53 = 8088得分

->s{s.scan(/[aiouy]+e*|e(?!d$|ly).|[td]ed|le$/).size}

这是一个匿名的Ruby函数,它使用正则表达式对音节进行计数。

该函数为以下每个实例添加一个音节:

  • 非的运行e元音,接着更多的零e小号
  • 一个e这是尾部的一部分edely与尾随的例外tedded小号
  • 尾随 le

分析

基本思想是计算元音的游动次数,但这本身并不十分准确([aeiouy]+正确率达到74%)。造成这种情况的主要原因是由于无声e,它可以修改以前的元音,而不会自己发声。例如,该单词slate有两个元音,但只有一个音节。

为了解决这个问题,我们e从正则表达式的第一部分中取出并单独对待。检测无声es很难,但是我发现两种情况经常发生:

  • 作为结尾的一部分ed(除非是a teddedlike settledsaddled),
  • 作为结尾的一部分evy(例如lovely

这些情况在其他情况下将被特别排除e.

.in 的原因e(?!d$|ly).是,如果有一个双元音(例如eaee),则消耗下一个字符,以便e不计算单词的末尾。但是尾部le 通常发音,使加回。

最后,元音运行被算作一个音节。尽管并非总是如此(例如curious),但通常很难弄清是否有多个音节。取iacelestialspatial,作为一个例子。

测试程序

我不太了解Ruby,因此不确定其打高尔夫球的程度。我确实通过咨询很多SO设法拼凑了一个测试程序:

cases = 0
correct = 0

s = "->s{s.scan(/[aiouy]+e*|e(?!d$|ly).|[td]ed|le$/).size}"

f = eval s

for i in 1 ... 8
    filepath = i.to_s + "-syllable-words.txt"
    file = File.open(filepath)

    while (line = file.gets)
        word = line.strip
        cases += 1
        if f.call(word) == i
            correct += 1
        end
    end
end

p "Correct: #{correct}/#{cases}, Length: #{s.length}, Score: #{correct - s.length*10}"

噢,您将标准设置得很高。在Python中,代码长度正好长20个字符,因此我对“ Vowel后跟非字母e”的实现给出了6638(正确的是7158)
2015年

2
@justhalf这基本上是我使用Ruby的唯一原因:PI通常将Python用于其他所有内容。
Sp3000

5

Python3、7935-10 * 71 = 7225

我的回答很简单:计算连续元音的运行次数,但不要删除任何最后一个e。

lambda w:len(''.join(" x"[c in"aeiouy"]for c in w.rstrip('e')).split())

剥离e后,将元音替换为,x并将所有其他字符替换为空格。结果重新连接成字符串,然后在空格上分割。方便地,开头和结尾的空格将被忽略(例如," x xx ".split()给定["x","xx"])。因此,结果列表的长度就是元音组的数量。

以下原始的83字节答案更准确,因为它最后只删除了一个e。因此,较新的单词在单词等问题上存在问题bee; 但是缩短的代码胜过这种效果。

lambda w:len(''.join(" x"[c in"aeiouy"]for c in(w[:-1]if'e'==w[-1]else w)).split())

测试程序:

syll = lambda w:len(''.join(c if c in"aeiouy"else' 'for c in w.rstrip('e')).split())

overallCorrect = overallTotal = 0
for i in range(1, 7):
    with open("%s-syllable-words.txt" % i) as f:
        words = f.read().split()
    correct = sum(syll(word) == i for word in words)
    total = len(words)
    print("%s: %s correct out of %s (%.2f%%)" % (i, correct, total, 100*correct/total))
    overallCorrect += correct
    overallTotal += total

print()
print("%s correct out of %s (%.2f%%)" % (overallCorrect, overallTotal, 100*overallCorrect/overallTotal))

显然,这太脏了,不够快,无法击败Sp3000的Ruby答案。; ^)


->s{s.scan(/([aiouy]|e(?!$))+/).size}得分7583。84%的简单成绩令人印象深刻。
Sp3000

1

Perl,8145-3 * 30 = 7845

使用最近提交之前的列表。

#!perl -lp
$_=s/(?!e[ds]?$)[aeiouy]+//g

这些文件最近已更新。我看了一下,却没有看到您在1个音节文件中命名的单词。
Sp3000

@ Sp3000,很奇怪。他们在那里更新根据我所看到的1小时前,并且仍有链接下的那些话:github.com/nathanmerrill/wordsbysyllables/blob/master/...
nutki

看起来@NathanMerrill弄乱了7小时前的更新:历史
Sp3000

@ Sp3000,谢谢。我将分数更新为旧版本。这些列表仍然有很多错误,但没有那么严重。
nutki'3

0

蟒蛇,5370-10 * 19 = 5180

该程序仅假设更长的单词意味着更多的音节。

lambda x:len(x)/6+1

我使用的测试程序是:

correct = 0
y = lambda x:len(x)/6+1
for i in xrange(1,8):
    f = file(str(i)+"-syllable-words.txt")
    lines = f.read().split("\n")
    f.close()
    correct += len([1 for line in lines if y(line)==i])
print correct

我们应该创建一个程序还是一个函数?您的不是程序,运行时不输出任何内容。
2015年

@justhalf我需要接受输入并产生输出的东西(即使该输出不是STDIO)
Nathan Merrill

顺便说一句,使用7并没有获得5150,而是4391。在我的测试中,最好使用len(x)/6(5377-190 = 5187)。
justhalf 2015年

@justhalf通过更新,我得到了5343,但是len(x)/ 6的得分肯定更差。我将发布我的测试程序。
内森·美林

readlines()在结果中包括换行符。所以你实际上是(len(x)+1)/7+1。您应该read().split('\n')改用。尽管我得到了5352的公式。
Justhalf 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.