Wie man die Silben in einem Wort zählt


22

Eingabe: Ihnen wird eine Zeichenfolge übergeben, die ein einzelnes englisches Wort enthält. Alle Buchstaben werden in Kleinbuchstaben geschrieben und die Zeichenfolge enthält keine nicht-alphabetischen Zeichen.

Ausgabe: Sie geben eine Ganzzahl von 1 bis 7 zurück, die angibt, wie viele Silben das Wort enthält.

Bewertung: Ihr Programm wird mit allen Wörtern in diesem Repository ausgeführt . Wenn Sie die Nrichtigen Wörter finden und Ihr Programm Mbyteslang ist, ist Ihre PunktzahlN-(M*10) . Die höchste Punktzahl gewinnt.

Um meine Silbenzählung zu generieren, habe ich diese als meine Wortliste verwendet und dies, um die Silben zu zählen.


Die 3-Silben-Wörter enthalten "inn" und "ruby". Die 2-Silben-Wörter enthalten diese: "irs", "ore", "roy", "yer". Davon abgesehen scheinen die Listen genau genug zu sein.
Nur die Hälfte des

@justhalf danke für die fänge. Das Erstellen der Listen war definitiv der schwierigste Teil der Herausforderung.
Nathan Merrill


3
Diese Herausforderung macht mir klar, wie albern Englisch sein kann. Nehmen Sie resumezum Beispiel ...
Sp3000

Antworten:


12

Ruby, 8618 korrekt (91,1%), 53 Byte, 8618 - 10 * 53 = 8088 Punkte

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

Dies ist eine anonyme Ruby-Funktion, die reguläre Ausdrücke verwendet, um Silben zu zählen.

Die Funktion fügt eine Silbe für jede Instanz von:

  • Eine Folge von Nicht- eVokalen, gefolgt von null oder mehr es
  • Ein ewas ist nicht Teil eines Trailings edoder ist ely, mit Ausnahme von Trailing tedoder deds
  • Ein schleppendes le

Analyse

Die Grundidee ist, Vokalläufe zu zählen, aber das ist an sich nicht sehr genau ([aeiouy]+ 74% richtig). Der Hauptgrund dafür liegt in der Stillee , die den vorherigen Vokalton verändert, ohne selbst ausgesprochen zu werden. Zum Beispiel hat das Wort slatezwei Vokale, aber nur eine Silbe.

Um damit umzugehen, nehmen wir e den ersten Teil des regulären Ausdrucks heraus und behandeln ihn separat. Das Erkennen stiller es ist schwierig, aber ich habe zwei Fälle gefunden, in denen sie häufig auftreten:

  • Als Teil eines Trailings ed(es sei denn, es ist einted oder dedwie settledoder saddled),
  • Im Rahmen eines Trailings evy (zB lovely)

Diese Fälle sind im Übrigen ausdrücklich ausgeschlossen e..

Der Grund für das .In e(?!d$|ly).ist, das nächste Zeichen zu verbrauchen, wenn es einen Doppelvokal gibt (z. B. eaoder ee), und damit eam Ende des Wortes nicht gezählt werden. Allerdings ein Nachlaufle ist Regel ausgesprochen, so dass wieder in hinzugefügt wird.

Schließlich werden Vokalläufe als eine Silbe gezählt. Dies ist möglicherweise nicht immer der Fall (z. B. curious), es ist jedoch oft schwierig herauszufinden, ob mehrere Silben vorhanden sind. Nehmen Sie das iavoncelestial und spatial, als Beispiel.

Testprogramm

Ich kenne Ruby nicht wirklich, also bin ich mir nicht sicher, wie gut es golfen kann. Es ist mir gelungen, ein Testprogramm zusammenzustellen, indem ich viel SO konsultiert habe:

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}"

Oh, du hast den Standard so hoch gemacht. In Python ist die Codelänge genau 20 Zeichen länger, sodass meine Implementierung Ihres "Vokals gefolgt von einem Buchstaben, der nicht e" ist, 6638 (7158 korrekt)
ergibt

2
@justhalf Es ist im Grunde der einzige Grund, warum ich Ruby benutze: PI benutzt normalerweise Python für alles andere.
Sp3000,

5

Python3, 7935-10 * 71 = 7225

Meine schnelle und schmutzige Antwort: Zähle die Läufe aufeinanderfolgender Vokale, aber entferne zuerst alle abschließenden Es.

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

Nach dem Entfernen der e werden die Vokale durch xund alle anderen Zeichen durch ein Leerzeichen ersetzt. Das Ergebnis wird wieder zu einer Zeichenfolge zusammengefasst und dann in Leerzeichen aufgeteilt. Praktischerweise wird das Leerzeichen am Anfang und Ende ignoriert (zB " x xx ".split()gibt ["x","xx"]). Die Länge der resultierenden Liste ist daher die Anzahl der Vokalgruppen.

Die ursprüngliche 83-Byte-Antwort unten war genauer, da nur ein einzelnes e am Ende entfernt wurde. Das neuere hat also Probleme für Wörter wie bee; aber der verkürzte Code überwiegt diesen Effekt.

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

Testprogramm:

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

Offensichtlich war dies zu schmutzig und nicht schnell genug, um die Ruby-Antwort von Sp3000 zu übertreffen. ; ^)


->s{s.scan(/([aiouy]|e(?!$))+/).size}Punkte 7583. 84% sind ziemlich beeindruckend für etwas so Einfaches.
Sp3000,

1

Perl, 8145-3 * 30 = 7845

Verwenden der Listen vor den letzten Commits.

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

Die Dateien wurden kürzlich aktualisiert. Ich habe einen Blick darauf geworfen und die Wörter, die Sie in der Silbendatei genannt haben, nicht gesehen.
Sp3000,

@ Sp3000, weired. Sie wurden vor 7 Stunden aktualisiert, was ich sehe, und es gibt immer noch diese Wörter unter diesem Link: github.com/nathanmerrill/wordsbysyllables/blob/master/…
nutki

Sieht aus wie @ NathanMerrill das Update vor 7 Stunden versaut: Geschichte .
Sp3000,

@ Sp3000, danke. Ich aktualisiere die Partitur auf die ältere Version. Diese Listen haben immer noch einige Fehler, sind aber nicht so schwerwiegend.
Nutki

0

Python, 5370-10 * 19 = 5180

Dieses Programm geht einfach davon aus, dass längere Wörter mehr Silben bedeuten.

lambda x:len(x)/6+1

Das Testerprogramm, das ich benutze, ist:

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

Sollen wir ein Programm oder eine Funktion erstellen? Dein Programm ist kein Programm, es gibt nichts aus, wenn es ausgeführt wird.
Nur die Hälfte des

@justhalf Ich brauche etwas, das Input akzeptiert und Output erzeugt (auch wenn dieser Output nicht STDIO ist)
Nathan Merrill

Übrigens habe ich nicht 5150 für die Verwendung von 7 erhalten, sondern 4391. In meinem Test ist es besser, len(x)/6stattdessen zu verwenden (5377-190 = 5187).
Nur die Hälfte des

@justhalf Mit den Updates bekomme ich 5343, aber definitiv eine schlechtere Punktzahl mit len ​​(x) / 6. Ich werde mein Testprogramm posten.
Nathan Merrill

readlines()Nimmt den Zeilenumbruch in das Ergebnis auf. Also ist deins eigentlich (len(x)+1)/7+1. Sie sollten read().split('\n')stattdessen verwenden. Ich habe zwar 5352 für diese Formel, aber.
Nur die Hälfte des
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.