Ruby, 8618 correcto (91.1%), 53 bytes, 8618-10 * 53 = 8088 puntaje
->s{s.scan(/[aiouy]+e*|e(?!d$|ly).|[td]ed|le$/).size}
Esta es una función de Ruby anónima que utiliza expresiones regulares para contar sílabas.
La función agrega una sílaba para cada instancia de:
- Una serie de no
e
vocales, seguida de cero de más e
s
- Un
e
que no es parte de un final ed
o ely
, con la excepción de final ted
o ded
s
- Un final
le
Análisis
La idea básica es contar series de vocales, pero esto por sí solo no es muy preciso ( [aeiouy]+
obtiene un 74% correcto). La razón principal de esto es debido al silencioe
, que modifica el sonido vocal anterior sin ser pronunciado. Por ejemplo, la palabra slate
tiene dos vocales pero solo una sílaba.
Para lidiar con esto, sacamos e
la primera parte de la expresión regular y la tratamos por separado. Detectar e
s silencioso es difícil, pero encontré dos casos en los que ocurren con frecuencia:
- Como parte de un seguimiento
ed
(a menos que sea un ted
o ded
como settled
o saddled
),
- Como parte de un seguimiento
evy
(por ejemplo lovely
)
Estos casos están específicamente excluidos de lo que de otro modo sería e.
.
La razón de la .
en e(?!d$|ly).
es consumir la siguiente Char si hay un doble vocal (por ejemplo, ea
o ee
), y de modo que e
al final de la palabra no se cuentan. Sin embargo, un trailing le
se pronuncia generalmente, de modo que se añade de nuevo.
Finalmente, las corridas vocales se cuentan como una sílaba. Si bien esto puede no ser siempre el caso (p curious
. Ej. ), A menudo es difícil determinar si hay varias sílabas. Tome el ia
de celestial
y spatial
, como ejemplo.
Programa de prueba
Realmente no conozco a Ruby, así que no estoy seguro de qué tan bien se puede jugar al golf. Sin embargo, logré reunir un programa de prueba consultando mucho 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}"