Рубі, 8618 правильних (91,1%), 53 байти, 8618 - 10 * 53 = 8088 балів
->s{s.scan(/[aiouy]+e*|e(?!d$|ly).|[td]ed|le$/).size}
Це анонімна функція Ruby, яка використовує регулярні вирази для підрахунку складів.
Функція додає склад для кожного примірника:
- Пробіг
e
неголосних з наступним нулем більше e
s
- Оно,
e
що не є частиною останнього ed
або ely
, за винятком трейлінгу ted
або ded
s
- Слід
le
Аналіз
Основна ідея - порахувати прогони голосних, але це само по собі не дуже точно ( [aeiouy]+
виходить 74% правильно). Основна причина цього - через беззвучнеe
, яке змінює попередній голосний звук, не будучи вимовленим самим собою. Наприклад, у слова slate
є два голосні, але лише один склад.
Щоб розібратися з цим, e
виймаємо першу частину регексу і обробляємо її окремо. Виявити безшумні e
s важко, але я виявив два випадки, коли вони трапляються часто:
- Як частина останньої
ed
(якщо вона не є ted
чи ded
подібною settled
чи saddled
),
- Як частина останнього
evy
(наприклад lovely
)
Ці випадки спеціально виключаються з того, що інакше було б e.
.
Причина в .
in e(?!d$|ly).
полягає в споживанні наступного знака, якщо є подвійний голосний (наприклад, ea
або ee
), і таким чином, щоб e
в кінці слова не зараховувались. Однак замикає le
це зазвичай вимовляється, так що додається назад.
Нарешті, голосні прогони рахуються як один склад. Хоча це не завжди так (наприклад curious
), часто важко розібратися, чи є кілька складів. Візьміть ia
з celestial
і spatial
, в якості прикладу.
Тестова програма
Я насправді не знаю Рубі, тому я не впевнений, наскільки добре це можна пограти в гольф. Мені вдалося скрепити програму тестування, консультувавшись з тим, хоча:
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}"