Ruby, 8618 правильных (91,1%), 53 байта, 8618 - 10 * 53 = 8088 баллов
->s{s.scan(/[aiouy]+e*|e(?!d$|ly).|[td]ed|le$/).size}
Это анонимная функция Ruby, которая использует регулярные выражения для подсчета слогов.
Функция добавляет слог для каждого экземпляра:
- В рабочем цикле не-
e
гласных, а затем нуля более e
с
- An,
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
, как пример.
Тестовая программа
Я действительно не знаю Руби, поэтому я не уверен, насколько хорошо он может быть в гольф. Мне удалось собрать воедино тестовую программу, посоветовавшись с большим количеством 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}"