Come contare le sillabe in una parola


22

Input: ti verrà passata una stringa contenente una sola parola inglese. Tutte le lettere saranno minuscole e non ci saranno caratteri non alfabetici nella stringa.

Output: restituirai un numero intero compreso tra 1 e 7 che rappresenta il numero di sillabe che ritieni siano presenti nella parola.

Punteggio: il tuo programma verrà eseguito su tutte le parole trovate in questo repository . Se ottieni le Nparole corrette e il tuo programma è Mgrande, allora il tuo punteggio è N-(M*10). Il punteggio più alto vince.

Per generare il mio conteggio delle sillabe, ho usato questo come mio elenco di parole e questo per contare le sillabe.


Le parole di 3 sillabe contengono "inn" e "ruby". Le parole di 2 sillabe contengono queste: "irs", "ore", "roy", "yer". Diverso da quello che le liste sembrano abbastanza accurate.
solo il

@justhalf grazie per quelle catture. La creazione delle liste è stata sicuramente la parte più difficile della sfida.
Nathan Merrill


3
Questa sfida mi sta facendo capire quanto può essere sciocco l'inglese. Prendi resumead esempio ...
Sp3000

Risposte:


12

Rubino, 8618 corretto (91,1%), 53 byte, 8618 - 10 * 53 = punteggio 8088

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

Questa è una funzione Ruby anonima che utilizza regex per contare le sillabe.

La funzione aggiunge una sillaba per ogni istanza di:

  • Una serie di non evocali, seguita da zero di più es
  • Un eche non fa parte di un trailing edo ely, ad eccezione di trailing tedo deds
  • Un finale le

Analisi

L'idea di base è contare le serie di vocali, ma questo di per sé non è molto preciso ( [aeiouy]+ottiene il 74% corretto). Il motivo principale di ciò è dovuto al silenzioe , che modifica il suono vocale precedente senza essere pronunciato. Ad esempio, la parola slateha due vocali ma solo una sillaba.

Per far fronte a questo, eliminiamo ela prima parte del regex e la trattiamo separatamente. Rilevare i messaggi di silenzio eè difficile, ma ho trovato due casi in cui si verificano spesso:

  • Come parte di un finale ed(a meno che non sia un tedo dedsimile settledo saddled),
  • Come parte di un finale evy(ad es. lovely)

Questi casi sono specificamente esclusi in ciò che altrimenti sarebbe e..

Il motivo per .in e(?!d$|ly).è di consumare il carattere successivo se c'è una doppia vocale (ad esempio eao ee), e in modo che ealla fine della parola non vengano conteggiati. Tuttavia, di solito le viene pronunciato un finale , quindi viene aggiunto nuovamente.

Infine, le corse vocaliche vengono conteggiate come una sillaba. Anche se questo potrebbe non essere sempre il caso (ad esempio curious), è spesso difficile capire se ci sono più sillabe. Prendi il iadi celestiale spatial, ad esempio.

Programma di test

Non conosco davvero Ruby, quindi non sono sicuro di come possa essere giocato a golf. Sono riuscito a mettere insieme un programma di test consultando molto SO però:

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, hai reso lo standard così elevato. In Python la lunghezza del codice è esattamente 20 caratteri più lunghi, quindi la mia implementazione della tua "vocale seguita da una lettera che non è e" dà 6638 (7158 corretto)
solo

2
@justhalf È fondamentalmente l'unico motivo per cui sto usando Ruby: PI normalmente uso Python per tutto il resto.
Sp3000

5

Python3, 7935-10 * 71 = 7225

La mia risposta rapida e sporca: conta le serie di vocali consecutive, ma rimuovi prima qualsiasi e finale.

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

Dopo aver rimosso le e, questo sostituisce le vocali con xe tutti gli altri personaggi con uno spazio. Il risultato viene unito nuovamente in una stringa e quindi suddiviso su spazi bianchi. Convenientemente, gli spazi all'inizio e alla fine vengono ignorati (ad es., " x xx ".split()["x","xx"]). La lunghezza dell'elenco risultante è quindi il numero di gruppi vocalici.

La risposta originale di 83 byte di seguito era più accurata perché alla fine rimuoveva solo una singola e. Il più recente ha quindi problemi per parole come bee; ma il codice abbreviato supera questo effetto.

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

Programma di test:

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

Evidentemente questo era troppo sporco e non abbastanza veloce per battere la risposta di Ruby di Sp3000. ; ^)


->s{s.scan(/([aiouy]|e(?!$))+/).size}segna 7583. L'84% è abbastanza impressionante per qualcosa di così semplice.
Sp3000

1

Perl, 8145-3 * 30 = 7845

Utilizzo degli elenchi precedenti ai commit recenti.

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

I file sono stati aggiornati di recente. Ho dato un'occhiata e non ho visto le parole che hai nominato nel file 1 sillaba.
Sp3000,

@ Sp3000, weired. Sono stati aggiornati 7 ore fa secondo quello che vedo, e ci sono ancora quelle parole sotto quel link: github.com/nathanmerrill/wordsbysyllables/blob/master/…
nutki

Sembra che @NathanMerrill abbia incasinato l'aggiornamento 7 ore fa: cronologia .
Sp3000,

@ Sp3000, grazie. Aggiornamento il punteggio alla versione precedente. Tali elenchi presentano ancora alcuni errori, ma non altrettanto gravi.
Nutki,

0

Python, 5370-10 * 19 = 5180

Questo programma presuppone semplicemente che parole più lunghe significano più sillabe.

lambda x:len(x)/6+1

Il programma tester che utilizzo è:

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

Dovremmo creare un programma o una funzione? Il tuo non è un programma, non emette nulla quando viene eseguito.
solo il

@justhalf Ho bisogno di qualcosa che accetti l'input e produca output (anche se quell'output non è STDIO)
Nathan Merrill

A proposito non ho ottenuto 5150 per l'utilizzo di 7, ma 4391. Nel mio test è meglio usare len(x)/6invece (5377-190 = 5187).
solo il

@justhalf Con gli aggiornamenti, sto ottenendo 5343, ma sicuramente sto ottenendo un punteggio peggiore con len (x) / 6. Pubblicherò il mio programma di test.
Nathan Merrill

readlines()include la nuova riga nel risultato. Quindi il tuo è in realtà (len(x)+1)/7+1. Dovresti usare read().split('\n')invece. Anche se ho ottenuto 5352 per quella formula, però.
solo il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.