単語の音節を数える方法


22

入力:単一の英語の単語を含む文字列が渡されます。すべての文字は小文字になり、文字列にはアルファベット以外の文字は含まれません。

出力:単語に含まれる音節の数を表す1〜7の整数を返します。

スコアリング:プログラムは、このリポジトリで見つかったすべての単語に対して実行されます。あなたが取得する場合Nの言葉は修正して、あなたのプログラムがあるM大規模なバイト、その後、あなたのスコアがありますN-(M*10)。最大のスコアが勝ちます。

音節カウントを生成するために、これを単語リストとして使用し、これを音節のカウントに使用ました。


3音節の単語には「inn」と「ruby」が含まれます。2音節の単語には、「irs」、「ore」、「roy」、「yer」が含まれます。それ以外は、リストは十分に正確に見えます。
ちょうど半分

@justhalfはそれらのキャッチに感謝します。リストを作成することは、間違いなく挑戦の最も困難な部分でした。
ネイサンメリル


3
この挑戦は、私がいかに愚かな英語ができるかを実感させています。テイクresume...例えば
SP3000

回答:


12

ルビー、8618正解(91.1%)、53バイト、8618-10 * 53 = 8088スコア

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

これは、音節をカウントするために正規表現を使用する匿名のRuby関数です。

この関数は、次のすべてのインスタンスに音節を追加します。

  • e母音の連続とそれに続く0個のes
  • eあるいない末尾の一部edまたはely末尾を除いて、tedまたはdedS
  • 末尾 le

分析

基本的な考え方は母音の連続音をカウントすることですが、これ自体はあまり正確ではありません([aeiouy]+74%正確になります)。これの主な理由は、無音eであるためです。これは、発音されずに前の母音を変更します。たとえば、単語にslateは2つの母音がありますが、音節は1つだけです。

これに対処するためeに、正規表現の最初の部分を取り出して個別に扱います。silent esの検出は困難ですが、頻繁に発生する2つのケースを見つけました。

  • 末尾の一環としてed(それはでない限りtedまたはdedのようなsettledまたはsaddled)、
  • 末尾の一部としてevy(例lovely

これらの場合はそうでなければ何であるかで特に除外されますe.

.in の理由e(?!d$|ly).は、二重母音(例:eaまたはee)がある場合に次の文字を消費しe、単語の終わりでカウントされないようにするためです。ただし、末尾le 通常発音されるため、追加されます。

最後に、母音の連続音は1音節としてカウントされます。これは常に当てはまるわけではありませんが(例curious:)、複数の音節があるかどうかを判断するのは難しい場合があります。取るiaのをcelestialしてspatial、一例として。

テストプログラム

私は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の後にない文字が続く」を実装すると、e6638(正しい7158)
15年

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バイトの回答は、最後に1つの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、おかしい。彼らはどこで何を参照してくださいに応じて7時間前に更新され、そのリンクの下で、それらの単語残っています:github.com/nathanmerrill/wordsbysyllables/blob/master/...
nutki

@NathanMerrillが7時間前に更新を台無しにしたようです:history
Sp3000

@ Sp3000、ありがとう。スコアを古いバージョンに更新します。これらのリストにはまだかなりの数のエラーがありますが、それほど深刻ではありません。
-nutki

0

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

プログラムまたは関数を作成する必要がありますか?Yoursはプログラムではなく、実行時に何も出力しません。
ちょうど半分

@justhalf入力を受け入れて出力を生成するものが必要です(その出力がSTDIOでなくても)
Nathan Merrill

ちなみに、7ではなく5391を使用しても5150は得られませんでした。テストでは、len(x)/6代わりに(5377-190 = 5187)を使用することをお勧めします。
ちょうど半分

@justhalf更新により、私は5343を取得していますが、len(x)/ 6で間違いなく悪いスコアを取得しています。テストプログラムを投稿します。
ネイサンメリル

readlines()結果に改行を含めます。あなたのは実際(len(x)+1)/7+1です。read().split('\n')代わりに使用する必要があります。とはいえ、私はその式で5352を得ましたが。
justhalf
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.