Java-Écriture d'un compteur de syllabes basé sur les spécifications


Spécification pour une syllabe:

Chaque groupe de voyelles adjacentes (a, e, i, o, u, y) compte comme une syllabe (par exemple, le "ea" dans "real" contribue à une syllabe, mais le "e...un " in "regal" compte comme deux syllabes). Cependant, un "e" à la fin d'un mot ne compte pas comme une syllabe. De plus, chaque mot a au moins une syllabe, même si les règles précédentes donnent un nombre de zéro.

Ma méthode countSyllables:

public int countSyllables(String word) {
    int count = 0;
    word = word.toLowerCase();
    for (int i = 0; i < word.length(); i++) {
        if (word.charAt(i) == '\"' || word.charAt(i) == '\'' || word.charAt(i) == '-' || word.charAt(i) == ',' || word.charAt(i) == ')' || word.charAt(i) == '(') {
            word = word.substring(0,i)+word.substring(i+1, word.length());
        }
    }
    boolean isPrevVowel = false;
    for (int j = 0; j < word.length(); j++) {
        if (word.contains("a") || word.contains("e") || word.contains("i") || word.contains("o") || word.contains("u")) {
            if (isVowel(word.charAt(j)) && !((word.charAt(j) == 'e') && (j == word.length()-1))) {
                if (isPrevVowel == false) {
                    count++;
                    isPrevVowel = true;
                }
            } else {
                isPrevVowel = false;
            }
        } else {
            count++;
            break;
        }
    }
    return count;
}

La méthode isVowel qui détermine si une lettre est une voyelle:

public boolean isVowel(char c) {
        if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
            return true;
        } else {
            return false;
        }
    }

Selon un collègue, cela devrait donner 528 syllabes lorsqu'il est utilisé sur ce texte, mais je peux sembler le faire égaler et je ne sais pas lequel d'entre nous est correct. Aidez-moi à développer ma méthode dans l'algorithme correct ou aidez-moi à montrer que c'est correct. Merci.

Author: mino, 2012-02-06

7 answers

L'un des problèmes pourrait être que vous appelez la méthode lover case sur l'entrée, mais vous ne l'affectez pas.

Donc, si vous changez

 word.toLowerCase();

À

word =  word.toLowerCase();

Aidera à coup sûr.

 3
Author: Damian Leszczyński - Vash, 2012-02-05 23:36:50

Cela devrait être facilement faisable avec une expression régulière:

Pattern p = Pattern.compile("[aeiouy]+?\w*?[^e]");
String[] result = p.split(WHAT_EVER_THE_INPUT_IS);
result.length

Veuillez noter qu'il n'est pas testée.

 0
Author: devsnd, 2012-02-06 01:47:56

Pas une réponse directe (et je vous en donnerais une si je pensais que c'était constructif, mon compte est d'environ 238 dans le dernier essai) mais je vais vous donner quelques indices qui seront fondamentaux pour créer la réponse:

  1. Divisez votre problème: Lisez les lignes, puis divisez les lignes en mots, puis comptez les syllabes pour chaque mot. Post-mots, comptez-les pour toutes les lignes.
  2. Pensez à l'ordre des choses: trouvez d'abord toutes les syllabes, et comptez chacune en "marchant" à travers mot. Facteur dans les cas particuliers par la suite.
  3. Pendant la conception, utilisez un débogueur pour parcourir votre code. Les chances sont assez élevées que vous commettiez des erreurs courantes comme la méthode toUpperCase(). Mieux vaut trouver ces erreurs, personne ne créera de code parfait la première fois.
  4. Imprimer sur la console (les utilisateurs avancés utilisent un journal et gardent les lignes de journal silencieuses dans le programme final). Assurez-vous de marquer les println à l'aide de commentaires et de les supprimer de l'implémentation finale. Imprimer des choses comme la ligne les nombres et les syllabes comptent afin que vous puissiez les comparer visuellement avec le texte.
  5. Si vous avez avancé un peu, vous pouvez utiliser Matcher.find (expressions régulières) à l'aide d'un Pattern pour trouver les syllabes. Les expressions régulières sont des bêtes difficiles à maîtriser. Une erreur commune est de leur faire trop en un coup.

De Cette façon, vous pouvez numériser rapidement le texte. Une des choses que vous découvrirez rapidement est que vous devrez faire face aux chiffres dans le texte. Si vous avez besoin de vérifier si un mot est en fait un mot, sinon, à vos règles, il aura au moins une seule syllabe.

Si vous avez le sentiment de répéter des choses, comme les méthodes isVowel et String.contains() utilisant le même ensemble de caractères, vous faites probablement quelque chose de mal. La répétition dans le code source est une odeur de code.

En utilisant des expressions rationnelles, j'ai compté environ 238 (au 4ème passage), mais je n'ai pas vraiment vérifié chaque syllabe (bien sûr).

1 14
2 17
3 17
4 15
5 15
6 14
7 16
8 19
9 17
10 17
11 16
12 19
13 18
14 15
15 18
16 15
17 16
18 17
19 16
20 17
21 17
22 19
23 17
24 16
25 17
26 17
27 16
28 17
29 15
30 17
31 19
32 23
33 0

 --- total --- 
538
 0
Author: Maarten Bodewes, 2012-02-06 23:19:43

Je suggère fortement que vous utilisiez l'API String de Java à sa pleine capacité. Par exemple, considérez String.diviser(expression régulière de chaîne):

Http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split%28java.lang.String%29

Cela prend une chaîne et une expression régulière, puis renvoie un tableau de toutes les sous-chaînes, en utilisant votre expression régulière comme un délimètre. Si vous faites correspondre votre expression régulière à toutes les consonnes ou espaces, vous vous retrouverez avec un tableau de chaînes qui sont vides (et ne représentent donc pas une consonne) ou une séquence de voyelles (qui représentent une consonne). Comptez ce dernier, et vous aurez une solution.

Une autre alternative qui tire également parti de l'API String et des expressions régulières est replaceAll:

Http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replaceAll%28java.lang.String,%20java.lang.String%29

Dans ce cas, vous souhaitez une régulière expression qui prend la forme [facultatif quelque chose qui n'est pas une voyelle][un ou plusieurs voyelles][facultatif quelque chose qui n'est pas une voyelle]. Exécutez cette expression régulière sur votre chaîne et remplacez-la par un seul caractère (par exemple "1"). Le résultat final est que chaque syllabe sera remplacée par un seul caractère. Ensuite, tout ce que vous devez faire est une chaîne.longueur() et vous saurez combien de syllabes que vous aviez.

Selon les exigences de votre solution, celles-ci peuvent ne pas fonctionner. Si c'est une question de devoirs en ce qui concerne la conception d'algorithmes, ce n'est certainement pas la réponse préférée, mais elle a l'avantage d'être concise et fait bon usage des API Java intégrées (et donc hautement optimisées).

 0
Author: Erica, 2013-11-24 04:53:28

Je viens d'inventer une nouvelle façon de compter les syllabes en Java.

Ma nouvelle bibliothèque, Le vérificateur de style Lawrence, peut être consultée ici: https://github.com/troywatson/Lawrence-Style-Checker

J'ai compté vos syllabes pour chaque mot en utilisant mon programme et affiché les résultats ici: http://pastebin.com/LyiBTcbb

Avec ma méthode de comptage des syllabes du dictionnaire, j'ai obtenu: 528 syllabes au total.

C'est le nombre exact que le questionneur a donné bon nombre de syllabes. Pourtant, je conteste toujours ce nombre pour les raisons décrites ci-dessous:

Taux de grève: 99,4% correct

Mots faux: 2 / 337 mots

Mots faux et mauvais compte syllabe: {resinous: 4, aardwolf: 3}

Voici mon code:

    Lawrence lawrence = new Lawrence();

    // Turn the text into an array of sentences.
    String sentences = ""
    String[] sentences2 = sentences.split("(?<=[a-z])\\.\\s+");

    int count = 0;

    for (String sentence : sentences2) {
        sentence = sentence.replace("-", " "); // split double words
        for (String word : sentence.split(" ")) {

            // Get rid of punctuation marks and spaces.
            word = lawrence.cleanWord(word);

            // If the word is null, skip it.
            if (word.length() < 1)
                continue;

            // Print out the word and it's syllable on one line.
            System.out.print(word + ",");
            System.out.println(lawrence.getSyllable(word));
            count += lawrence.getSyllable(word);
        }
    }
    System.out.println(count);

Bam!

 0
Author: troy, 2015-09-25 15:48:00
    private static int countSyllables(String word)
{
    //System.out.print("Counting syllables in " + word + "...");
    int numSyllables = 0;
    boolean newSyllable = true;
    String vowels = "aeiouy";
    char[] cArray = word.toCharArray();
    for (int i = 0; i < cArray.length; i++)
    {
        if (i == cArray.length-1 && Character.toLowerCase(cArray[i]) == 'e' 
                && newSyllable && numSyllables > 0) {
            numSyllables--;
        }
        if (newSyllable && vowels.indexOf(Character.toLowerCase(cArray[i])) >= 0) {
            newSyllable = false;
            numSyllables++;
        }
        else if (vowels.indexOf(Character.toLowerCase(cArray[i])) < 0) {
            newSyllable = true;
        }
    }
    //System.out.println( "found " + numSyllables);
    return numSyllables;
}

Une autre implémentation peut être trouvée ci-dessous lien pastebin: https://pastebin.com/q6rdyaEd

 0
Author: DISHA, 2017-04-16 17:39:52

Ceci est mon implémentation pour compter les syllabes

protected int countSyllables(String word)
{
    // getNumSyllables method in BasicDocument (module 1) and 
    // EfficientDocument (module 2).
    int syllables = 0;
    word = word.toLowerCase();
    if(word.contains("the ")){
        syllables ++;
    }
    String[] split = word.split("e!$|e[?]$|e,|e |e[),]|e$");

    ArrayList<String> tokens = new ArrayList<String>();
    Pattern tokSplitter = Pattern.compile("[aeiouy]+");

    for (int i = 0; i < split.length; i++) {
        String s = split[i];
        Matcher m = tokSplitter.matcher(s);

        while (m.find()) {
            tokens.add(m.group());
        }
    }

    syllables += tokens.size();
    return syllables;
}

Cela fonctionne bien pour moi.

 -1
Author: Ima Miri, 2016-05-27 04:24:15