Cara menghitung suku kata dalam sebuah kata

22

Input: Anda akan diberikan string yang berisi satu kata bahasa Inggris. Semua huruf akan menjadi huruf kecil, dan tidak akan ada karakter non-alfabet dalam string.

Keluaran: Anda akan mengembalikan bilangan bulat dari 1 hingga 7 yang mewakili berapa banyak suku kata yang menurut Anda ada dalam kata.

Penilaian: Program Anda akan dijalankan terhadap semua kata yang ditemukan di repositori ini . Jika Anda mendapatkan Nkata-kata yang benar, dan program Anda Mberukuran besar, maka skor Anda adalah N-(M*10). Skor terbanyak menang.

Untuk menghasilkan jumlah suku kata saya, saya menggunakan ini sebagai daftar kata saya dan ini untuk menghitung suku kata.

Nathan Merrill
sumber
3-suku kata-kata mengandung "inn" dan "ruby". 2-suku kata-kata mengandung ini: "irs", "ore", "roy", "yer". Selain itu daftar itu tampaknya cukup akurat.
justhalf
@ justhalf terima kasih atas tangkapan itu. Membuat daftar jelas merupakan bagian tersulit dari tantangan.
Nathan Merrill
3
Tantangan ini membuat saya sadar betapa bodohnya bahasa Inggris. Ambil resumecontoh ...
Sp3000

Jawaban:

12

Ruby, 8618 benar (91,1%), 53 byte, 8618 - 10 * 53 = 8088 skor

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

Ini adalah fungsi Ruby anonim yang menggunakan regex untuk menghitung suku kata.

Fungsi ini menambahkan suku kata untuk setiap instance dari:

  • Serangkaian non- evokal, diikuti oleh nol es lebih
  • Suatu eyang bukan bagian dari trailing edatau ely, dengan pengecualian trailing tedatau deds
  • A tertinggal le

Analisis

Ide dasarnya adalah untuk menghitung jumlah huruf vokal, tetapi ini dengan sendirinya tidak terlalu akurat ( [aeiouy]+mendapatkan 74% benar). Alasan utama untuk ini adalah karena diame , yang memodifikasi suara vokal sebelumnya sementara tidak diucapkan sendiri. Misalnya, kata tersebut slatememiliki dua vokal tetapi hanya satu suku kata.

Untuk mengatasinya, kami mengambil ebagian pertama dari regex dan memperlakukannya secara terpisah. Mendeteksi silent es sulit, tetapi saya menemukan dua kasus di mana mereka sering terjadi:

  • Sebagai bagian dari Trailing ed(kecuali itu adalah tedatau dedseperti settledatau saddled),
  • Sebagai bagian dari trailing evy(mis. lovely)

Kasus-kasus ini secara khusus dikecualikan dalam apa yang seharusnya e..

Alasan untuk .di e(?!d$|ly).adalah untuk mengkonsumsi char berikutnya jika ada vokal ganda (misalnya eaatau ee), dan epada akhir kata tidak dihitung. Namun Trailing le yang biasanya diucapkan, sehingga ditambahkan kembali.

Akhirnya, vokal berjalan dihitung sebagai satu suku kata. Meskipun hal ini tidak selalu terjadi (mis. curious), Seringkali sulit untuk mengetahui apakah ada banyak suku kata. Ambil iadari celestialdan spatial, sebagai contoh.

Program uji

Saya tidak begitu mengenal Ruby, jadi saya tidak yakin seberapa bagus golfnya. Saya berhasil mengikis bersama program uji dengan berkonsultasi banyak SO meskipun:

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}"
Sp3000
sumber
Aww, kamu membuat standar begitu tinggi. Dengan Python, panjang kode persis 20 karakter lebih lama, jadi penerapan "Vowel Anda diikuti dengan huruf yang bukan e" memberi 6638 (7158 benar)
justhalf
2
@justhalf Ini pada dasarnya satu-satunya alasan mengapa saya menggunakan Ruby: PI biasanya menggunakan Python untuk yang lainnya.
Sp3000
5

Python3, 7935 - 10 * 71 = 7225

Jawaban cepat-dan-kotor saya: menghitung vokal berturut-turut, tetapi hilangkan e akhir apa pun terlebih dahulu.

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

Setelah melepaskan e, ini menggantikan vokal dengan xdan semua karakter lain dengan spasi. Hasilnya digabungkan kembali menjadi string dan kemudian dipisah pada spasi putih. Secara mudah, spasi putih di awal dan akhir diabaikan (mis. " x xx ".split()Memberi ["x","xx"]). Oleh karena itu, panjang daftar yang dihasilkan adalah jumlah grup vokal.

Jawaban asli, 83 byte di bawah ini lebih akurat karena hanya menghapus satu e di bagian akhir. Dengan demikian yang lebih baru memiliki masalah untuk kata-kata seperti bee; tetapi kode yang diperpendek melebihi efek itu.

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

Program uji:

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

Jelas ini terlalu kotor dan tidak cukup cepat untuk mengalahkan jawaban Ruby Sp3000. ; ^)

DLosc
sumber
->s{s.scan(/([aiouy]|e(?!$))+/).size}skor 7583. 84% cukup mengesankan untuk sesuatu yang sangat sederhana.
Sp3000
1

Perl, 8145 - 3 * 30 = 7845

Menggunakan daftar dari sebelum komit terbaru.

#!perl -lp
$_=s/(?!e[ds]?$)[aeiouy]+//g
nutki
sumber
File-file telah diperbarui baru-baru ini. Saya melihat dan tidak melihat kata-kata yang Anda sebutkan dalam file 1 suku kata.
Sp3000
@ Sp3000, lelah. Mereka di mana diperbarui 7 jam yang lalu sesuai dengan apa yang saya lihat, dan masih ada kata-kata di bawah tautan itu: github.com/nathanmerrill/wordsbysyllables/blob/master/…
nutki
Sepertinya @NathanMerrill mengacaukan pembaruan 7 jam yang lalu: history .
Sp3000
@ Sp3000, terima kasih. Saya memperbarui skor ke versi yang lebih lama. Daftar itu masih memiliki beberapa kesalahan, tetapi tidak separah itu.
nutki
0

Python, 5370-10 * 19 = 5180

Program ini mengasumsikan bahwa kata yang lebih panjang berarti lebih banyak suku kata.

lambda x:len(x)/6+1

Program tester yang saya gunakan adalah:

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
Nathan Merrill
sumber
Haruskah kita membuat program atau fungsi? Milik Anda bukan program, tidak menghasilkan apa-apa saat dijalankan.
justhalf
@ justhalf Saya memerlukan sesuatu yang menerima input dan menghasilkan output (bahkan jika output itu bukan STDIO)
Nathan Merrill
Btw saya tidak mendapatkan 5150 untuk menggunakan 7, tetapi 4391. Dalam pengujian saya lebih baik menggunakan len(x)/6sebagai gantinya (5377-190 = 5187).
justhalf
@justhalf Dengan pembaruan, saya mendapatkan 5343, tapi pasti mendapatkan skor lebih buruk dengan len (x) / 6. Saya akan memposting program pengujian saya.
Nathan Merrill
readlines()termasuk baris baru dalam hasilnya. Jadi milikmu sebenarnya (len(x)+1)/7+1. Anda harus menggunakannya read().split('\n')sebagai gantinya. Meskipun saya mendapat 5352 untuk formula itu.
justhalf