Rubinowy, 8618 poprawny (91,1%), 53 bajty, 8618 - 10 * 53 = wynik 8088
->s{s.scan(/[aiouy]+e*|e(?!d$|ly).|[td]ed|le$/).size}
Jest to anonimowa funkcja Ruby, która używa wyrażeń regularnych do liczenia sylab.
Funkcja dodaje sylabę do każdego wystąpienia:
- Seria non-
e
samogłosek, po której następuje zero lub więceje
s
e
Który nie częścią tylną ed
i ely
, z wyjątkiem końcowe ted
lubded
S
- Wleczenie
le
Analiza
Podstawową ideą jest zliczanie samogłosek, ale samo to nie jest zbyt dokładne ( [aeiouy]+
uzyskuje 74% poprawności). Głównym tego powodem jest cicha zmianae
, która modyfikuje poprzednią samogłoskę, ale sama nie jest wymawiana. Na przykład słowoslate
ma dwie samogłoski, ale tylko jedną sylabę.
Aby sobie z tym poradzić, wyjmujemy e
pierwszą część wyrażenia regularnego i traktujemy ją osobno. Wykrywanie cichych e
s jest trudne, ale znalazłem dwa przypadki, w których często występują:
- Jako część tylną
ed
(o ile nie jest to ted
lub ded
podobne settled
lubsaddled
)
- W ramach końcowego
evy
(np. lovely
)
Przypadki te są wyraźnie wykluczone z tego, co byłoby inaczej e.
.
Powodem .
in e(?!d$|ly).
jest użycie następnego znaku, jeśli występuje podwójna samogłoska (np. ea
Lub ee
), a więc e
na końcu słowa nie są liczone. Jednak końcowe le
jest zwykle wymawiane, więc jest dodawane z powrotem.
Wreszcie, samogłoski są liczone jako jedna sylaba. Chociaż nie zawsze tak jest (np. curious
), Często trudno jest ustalić, czy istnieje wiele sylab. Weź ia
od celestial
ispatial
, jako przykład.
Program testowy
Naprawdę nie znam Ruby, więc nie jestem pewien, jak dobrze można grać w golfa. Udało mi się zeskrobać program testowy, konsultując wiele 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}"