Cách đếm các âm tiết trong một từ


22

Đầu vào: Bạn sẽ được thông qua một chuỗi chứa một từ tiếng Anh. Tất cả các chữ cái sẽ là chữ thường và sẽ không có các ký tự không phải là chữ cái trong chuỗi.

Đầu ra: Bạn sẽ trả về một số nguyên từ 1 đến 7 đại diện cho số lượng âm tiết bạn nghĩ trong từ.

Chấm điểm: Chương trình của bạn sẽ được chạy với tất cả các từ được tìm thấy trên kho lưu trữ này . Nếu bạn nhận được các Ntừ chính xác và chương trình của bạn là Mbyte lớn, thì điểm của bạn là N-(M*10). Điểm số lớn nhất chiến thắng.

Để tạo ra số âm tiết của tôi, tôi đã sử dụng làm danh sách từ của tôi và số này để đếm các âm tiết.


Các từ có 3 âm tiết chứa "inn" và "ruby". Các từ có 2 âm tiết chứa các từ này: "irs", "ore", "roy", "yer". Khác hơn là danh sách có vẻ đủ chính xác.
cần

@justhalf cảm ơn bạn vì những sản phẩm khai thác. Tạo các danh sách chắc chắn là phần khó nhất của thử thách.
Nathan Merrill


3
Thử thách này đang khiến tôi nhận ra tiếng Anh ngớ ngẩn đến mức nào. Lấy resumeví dụ ...
Sp3000 04/03/2015

Câu trả lời:


12

Ruby, 8618 đúng (91,1%), 53 byte, 8618 - 10 * 53 = 8088 điểm

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

Đây là một hàm Ruby ẩn danh sử dụng biểu thức chính quy để đếm các âm tiết.

Hàm thêm một âm tiết cho mọi trường hợp:

  • Một loạt các enguyên âm, theo sau là 0 của nhiều es
  • Một ecái không phải là một phần của dấu edhoặc ely, ngoại trừ dấu tedhoặc deds
  • Một dấu le

Phân tích

Ý tưởng cơ bản là đếm số lần chạy nguyên âm, nhưng điều này tự nó không chính xác lắm ( [aeiouy]+được 74% chính xác). Lý do chính cho điều này là do sự im lặnge , điều chỉnh âm nguyên âm trước đó trong khi không được phát âm. Ví dụ, từ slatenày có hai nguyên âm nhưng chỉ có một âm tiết.

Để giải quyết vấn đề này, chúng tôi eloại bỏ phần đầu tiên của regex và xử lý nó một cách riêng biệt. Phát hiện sự im lặng elà khó, nhưng tôi đã tìm thấy hai trường hợp chúng xảy ra thường xuyên:

  • Là một phần của dấu vết ed(trừ khi nó là tedhoặc dedthích settledhoặc saddled),
  • Là một phần của dấu vết evy(ví dụ lovely)

Những trường hợp này được đặc biệt loại trừ trong những gì sẽ được e..

Lý do cho việc .nhập e(?!d$|ly).là để tiêu thụ char tiếp theo nếu có nguyên âm đôi (ví dụ eahoặc ee), và do đó eở cuối từ không được tính. Tuy nhiên một dấu le thường phát âm, do đó được bổ sung trở lại trong.

Cuối cùng, các nguyên âm chạy được tính là một âm tiết. Mặc dù điều này có thể không phải luôn luôn như vậy (ví dụ curious), nhưng thường rất khó để biết liệu có nhiều âm tiết hay không. Lấy iacủa celestialspatial, như một ví dụ.

Chương trình kiểm tra

Tôi thực sự không biết Ruby nên tôi không chắc nó có thể chơi golf tốt như thế nào. Tôi đã cố gắng để cùng nhau tạo ra một chương trình thử nghiệm bằng cách tham khảo rất nhiều 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}"

Aww, bạn đã làm cho tiêu chuẩn rất cao. Trong Python, độ dài mã dài hơn chính xác 20 ký tự, do đó, việc tôi thực hiện "Nguyên âm theo sau là một chữ cái không e" mang lại cho 6638 (7158 chính xác)
cần

2
@justhalf Về cơ bản, đó là lý do duy nhất khiến tôi sử dụng Ruby: PI thường sử dụng Python cho mọi thứ khác.
Sp3000

5

Python3, 7935 - 10 * 71 = 7225

Câu trả lời nhanh và bẩn của tôi: đếm các nguyên âm liên tiếp, nhưng loại bỏ bất kỳ e cuối cùng nào.

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

Sau khi loại bỏ các e, điều này thay thế các nguyên âm với xvà tất cả các ký tự khác bằng một khoảng trắng. Kết quả được nối lại thành một chuỗi và sau đó phân chia trên khoảng trắng. Thuận tiện, khoảng trắng ở đầu và cuối bị bỏ qua (ví dụ: " x xx ".split()cho ["x","xx"]). Do đó, độ dài của danh sách kết quả là số lượng nhóm nguyên âm.

Câu trả lời gốc 83 byte dưới đây chính xác hơn vì nó chỉ xóa một e ở cuối. Do đó, cái mới hơn có vấn đề cho các từ như bee; nhưng mã rút ngắn vượt xa hiệu ứng đó.

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

Chương trình kiểm tra:

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

Rõ ràng điều này quá bẩn và không đủ nhanh để đánh bại câu trả lời Ruby của Sp3000. ; ^)


->s{s.scan(/([aiouy]|e(?!$))+/).size}điểm 7583. 84% khá ấn tượng cho một cái gì đó quá đơn giản.
Sp3000

1

Perl, 8145 - 3 * 30 = 7845

Sử dụng các danh sách từ trước khi cam kết gần đây.

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

Các tập tin đã được cập nhật gần đây. Tôi đã xem và không thấy những từ bạn đặt tên trong tệp 1 âm tiết.
Sp3000

@ Sp3000, đã sử dụng. Họ nơi cập nhật 7 giờ trước theo những gì tôi nhìn thấy, và vẫn còn là những lời dưới liên kết: github.com/nathanmerrill/wordsbysyllables/blob/master/...
nutki

Có vẻ như @NathanMerrill đã làm rối bản cập nhật 7 giờ trước: history .
Sp3000

@ Sp3000, cảm ơn. Tôi cập nhật điểm số lên phiên bản cũ hơn. Những danh sách đó vẫn còn khá nhiều lỗi, nhưng không nghiêm trọng.
nutki

0

Con trăn, 5370-10 * 19 = 5180

Chương trình này chỉ đơn giản giả định rằng các từ dài hơn có nghĩa là nhiều âm tiết hơn.

lambda x:len(x)/6+1

Chương trình thử nghiệm tôi sử dụng là:

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

Chúng ta nên tạo một chương trình hoặc một chức năng? Của bạn không phải là một chương trình, nó không tạo ra gì khi chạy.
cần

@justhalf Tôi cần một cái gì đó chấp nhận đầu vào và tạo đầu ra (ngay cả khi đầu ra đó không phải là STDIO)
Nathan Merrill

Btw Tôi đã không nhận được 5150 cho việc sử dụng 7, nhưng 4391. Trong thử nghiệm của tôi, tốt hơn là sử dụng len(x)/6thay thế (5377-190 = 5187).
ngay lúc

@justhalf Với các bản cập nhật, tôi nhận được 5343, nhưng chắc chắn nhận được điểm kém hơn với len (x) / 6. Tôi sẽ đăng chương trình thử nghiệm của tôi.
Nathan Merrill

readlines()bao gồm các dòng mới trong kết quả. Vì vậy, của bạn là thực sự (len(x)+1)/7+1. Bạn nên sử dụng read().split('\n')thay thế. Mặc dù tôi đã có 5352 cho công thức đó, mặc dù.
cần
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.