Bir kelime ile heceleri nasıl sayılır


22

Giriş: Tek bir ingilizce kelime içeren bir dize geçilecektir. Tüm harfler küçük harf olacak ve dizgede alfabetik olmayan karakterler bulunmayacak.

Çıktı: Kelimede kaç tane hece olduğunu gösteren 1 ile 7 arasında bir tam sayı döndürürsünüz.

Puanlama: Programınız bu depoda bulunan tüm kelimelere karşı çalıştırılacaktır . Eğer Nkelimeleri doğru alırsanız ve programınızM bayt büyükse, o zaman puanınız N-(M*10). En büyük puan kazanır.

Benim hece sayısını üretmek için, kullandığım bu benim kelime listesi olarak ve bu heceleri saymak.


3 heceli kelimeler "han" ve "yakut" içerir. 2 heceli sözcükler şunları içerir: "irs", "cevher", "roy", "yer". Bunun dışında listeler yeterince doğru görünüyor.
justhalf

Sadece bu yakalamalar için teşekkür ederim. Listeleri oluşturmak kesinlikle mücadelenin en zor kısmıydı.
Nathan Merrill,


3
Bu zorluk, İngilizcenin ne kadar aptal olabileceğini anlamamı sağlıyor. resumeÖrneğin al ...
Sp3000

Yanıtlar:


12

Ruby, 8618 doğru (% 91.1), 53 bayt, 8618 - 10 * 53 = 8088 puan

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

Bu, heceleri saymak için regexes kullanan isimsiz bir Ruby işlevidir.

İşlev, her örneği için bir hece ekler:

  • eÜnlü olmayan bir harf, ardından sıfırdan daha fazlasıe s
  • Bir eolan olmayan bir eğik bir parçası edya da elyarka hariç olmak üzere, tedya daded s
  • Bir iz le

analiz

Temel fikir, ünlü harfleri saymaktır, ancak bu tek başına çok doğru değildir ( [aeiouy]+% 74 doğru olur). Bunun asıl nedeni , önceki sesli sesi kendisi söylenmeden değiştiren sessizliktire . Örneğin, kelimeslate iki ünlü harfleri var ama sadece tek heceli.

eBununla başa çıkmak için , regex'in ilk bölümünden ayrılıyor ve ayrı olarak işlem yapıyoruz . Sessiz es algılamak zordur, ancak sık sık meydana geldiği iki durum buldum:

  • Bir izin parçası olarak ed(bir tedveya dedbenzeri olmadığı sürece settledveyasaddled ),
  • Bir izlemenin parçası olarak evy(örneğin lovely)

Bu durumlar, aksi takdirde ne olacağı konusunda özellikle dışlanır e. .

Sebebi .in e(?!d$|ly).orada bir çift sesli harf (örn ise bir sonraki kömürü tüketmek olduğunu eaveya ee) ve böylece ekelimenin sonundaki sayılmaz. Bununla birlikte bir arka le olan geri ilave edilir, bu nedenle genellikle, belirgin.

Son olarak, sesli sayılar tek heceli olarak sayılır. Bu her zaman böyle olmasa da (örneğin curious), çoklu hecelerin olup olmadığını anlamak genellikle zordur. Al iaait celestialve spatialbir örnek olarak,.

Test programı

Ruby'yi gerçekten tanımıyorum, bu yüzden ne kadar iyi golf oynayabileceğinden emin değilim. Çok fazla SO danışarak bir test programını bir araya getirmeyi başardım:

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

Aww, standardı çok yüksek yaptın. Senin benim uygulanması "sesli harf değil bir harf tarafından takip yüzden Python kod uzunluğu, tam 20 karakter daha uzun e" verir 6638 (7158 doğru)
justhalf

2
@justhalf Temel olarak Ruby kullanmamın tek nedeni bu: PI normalde Python'u her şey için kullanıyor.
Sp3000,

5

Python3,7935-10 * 71 = 7225

Hızlı ve kirli cevabım: ardışık sesli harflerin sayımını say, ancak ilk e harfini kaldır.

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

E'leri çıkardıktan sonra, bu sesli harfleri xve tüm diğer karakterleri boşluk bırakarak değiştirir . Sonuç bir dizgede tekrar birleştirilir ve sonra boşlukta bölünür. Elverişli, başında ve sonunda boşluk dikkate alınmaz ( " x xx ".split()verir["x","xx"] ). Sonuçta ortaya çıkan listenin uzunluğu, ünlü grupların sayısıdır.

Aşağıdaki asıl, 83 baytlık cevap daha doğruydu çünkü sonuçta yalnızca bir e kaldı. Yeni olan, bu nedenle bee; ancak kısaltılmış kod bu etkiden daha ağır basar.

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

Test programı:

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

Açıkçası bu çok kirli ve Sp3000'in Ruby cevabını yenecek kadar hızlı değildi. ; ^)


->s{s.scan(/([aiouy]|e(?!$))+/).size}7583 puan alıyor. 84% çok basit bir şey için oldukça etkileyici.
Sp3000,

1

Perl, 8145 - 3 * 30 = 7845

Listeleri, son kararlardan önce kullanmak.

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

Dosyalar yakın zamanda güncellendi. Bir göz attım ve 1 heceli dosyada sizin adınızı yazdığınız kelimeleri görmedim.
Sp3000

@ Sp3000, weired. Onlar nerede 7 saat gördüklerimi göre önce güncellendi ve bu bağlantıya altında o sözler hala vardır: github.com/nathanmerrill/wordsbysyllables/blob/master/...
Nutki

@NathanMerrill 7 saat önce güncellemeyi berbat etti gibi görünüyor: geçmiş .
Sp3000

@ Sp3000, teşekkürler. Skoru eski sürüme güncellerim. Bu listelerde hala birkaç hata var, ancak bu kadar şiddetli değil.
nutki

0

Python, 5370-10 * 19 = 5180

Bu program basitçe daha uzun kelimelerin daha fazla heceli anlamına geldiğini varsayar.

lambda x:len(x)/6+1

Kullandığım test programı:

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

Bir program mı yoksa işlev mi oluşturmalıyız? Sizinki bir program değil, çalıştırıldığında hiçbir şey vermiyor.
justhalf

@justhalf Girdiyi kabul eden ve çıktı üreten bir şeye ihtiyacım var (bu çıktı STDIO olmasa bile)
Nathan Merrill

BT 7'yi kullanmak için 5150 almadım, ancak 4391. Testimde len(x)/6bunun yerine kullanmak daha iyi (5377-190 = 5187).
justhalf

@justhalf Güncellemeler ile 5343 alıyorum, ancak kesinlikle len (x) / 6 ile daha kötü bir skor elde ediyorum. Test programımı göndereceğim.
Nathan Merrill,

readlines()sonuçtaki yeni satırı da içerir. Yani seninki aslında (len(x)+1)/7+1. Bunun read().split('\n')yerine kullanmalısın . Yine de bu formül için 5352 aldım.
justhalf
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.