Syllabify mots anglais - genre de

11

Vous êtes chargé d'écrire un programme qui syllabifie les mots dans une chaîne de texte, en les séparant par un tiret. Ce serait beaucoup de travail, donc vous voulez sauter certaines parties, principalement parce que vous ne voulez pas avoir un tableau des prononciations requises pour un algorithme parfait. Vous voulez aussi le rendre aussi court (et donc illisible et non maintenable) que possible comme une revanche pour avoir reçu cette mission.

Vous avez deux choix:

  • Écrivez un programme qui prend la chaîne de STDIN et renvoie le résultat à STDOUT.
  • Écrivez une fonction qui prend la chaîne en tant que paramètre unique et renvoie le résultat.

spécification

  • Dans ce cas, chaîne signifie toute construction de type chaîne dans la langue de votre choix (tableaux d'octets, tableaux de caractères, chaînes ...).
  • Les voyelles sont a, e, i, o, u
  • La chaîne donnée a des 1 <= n <= 10mots, où chacun a une longueur entre les 1 - 30caractères, inclus .. Votre sortie doit être ces mots avec un trait d'union.
  • Toutes les lettres sont en minuscules et les mots sont toujours séparés par des espaces. Ainsi, l'entrée se compose de caractères[a-z ]
  • Appliquez les règles par ordre d'importance.
  • Lorsqu'un mot est divisé, recommencez avec la moitié droite du mot.

Règles de syllabification , par ordre d'importance

Deux mêmes voyelles consécutives compter que l' un (ie. feetNe comporte qu'une seule voyelle, mais beatet findingont deux). Chaque syllabe a exactement une voyelle, donc il y a une syllabe pour chaque voyelle.

  1. Si le mot entier n'a que quatre lettres, renvoyez-le inchangé. (sautez ceci pour le reste du mot)
  2. Si le mot n'a qu'une voyelle, renvoyez-le inchangé.
  3. Si le mot a deux voyelles consécutives, divisez-les (c.-à-d. diaspora-> di-as-po-ra)
  4. Lorsque deux consonnes ou plus se trouvent entre deux voyelles (identiques ou différentes), divisez après la première consonne (c'est-à-dire sis-ter) à moins que la partie consonne ne soit ck, auquel cas divisez le mot après. (c'est-à-dire nickel-> nick-el)
  5. Quand a yvient entre deux voyelles, divisez le mot après (par exemple paying-> pay-ing).
  6. Quand une consonne vient entre deux voyelles (identiques ou différentes), divisez avant la consonne (ie. dra-gon)
  7. Renvoyez le mot inchangé si aucune division n'a pu être effectuée.

J'ai choisi ces règles, car elles peuvent être appliquées récursivement sans problème et ne nécessitent aucune table de prononciation. Ainsi, ils ne sont pas exacts et, par exemple, la règle n ° 5 est souvent incorrecte. Dans le cas général cependant, c'est le cas.

Exemple

In:  hello world
Out: hel-lo world

In:  have a nice day
Out: have a nice day

In:  pour some nickel and xenon there
Out: pour some nick-el and xe-non the-re
seequ
la source
Êtes-vous sûr x-e-non? Référence pour la règle # 4?
John Dvorak
@JanDvorak "Lorsqu'un mot est divisé, recommencez avec la moitié droite du mot.", Suivi de la règle n ° 6.
seequ
Je veux dire, la règle # 4 ne devrait-elle pas seulement être divisée entre les syllabes?
John Dvorak
1
La règle n ° 1 traite des mots de quatre lettres. Qu'en est-il des mots de moins de quatre lettres? par exemplelua
Digital Trauma
1
@DigitalTrauma Ils sont prosternés normalement, mais ont rarement deux syllabes.
seequ

Réponses:

6

Rubis, 144 octets

Si nous optons pour l'impossible, que diriez-vous d'un seul regex géant?

puts gets.split.map {|w| w.scan(/(^.{4}$|[^aeiou]*([aeiou])\2?((?=[^aeiouy]?[aeiou])|ck|[^aeiou]((?=.*[aeiou])|.*$)|$))/).map(&:first)*'-'}*' '

une sortie:

echo "hello world" | ruby syllable.rb
hel-lo world

echo "have a nice day" | ruby syllable.rb
have a nice day

echo "pour some nickel and xenon in there" | ruby syllable.rb
pour some nick-el and xe-non in the-re

echo "diaspora dragon paying sister hemlock happy quicksilver" | ruby syllable.rb
di-as-po-ra dra-gon pay-ing sis-ter hem-lock happy qu-ick-sil-ver
YenTheFirst
la source
8

Lua, 292

Lua n'était peut-être pas la meilleure langue pour le faire, mais cela fonctionne. Cela coule à peu près comme la question posée. Les règles sont principalement en ordre avec quelques optimisations: # 2 est ignoré (il n'est pas nécessaire sauf s'il y a un mot d'une voyelle avec "ck" au début), et les règles ck et y sont passées avant le reste de # 4 et # 6, qui sont combinés. Étant donné que certaines voyelles du mot doivent être capturées deux fois (après un tiret et avant un autre), cette recherche est effectuée deux fois.

i=io.read()v="([aeiou])"for s in i:gfind("%l+ ?")do
if s:len()~=4 then
s=s:gsub(v..v,function(x,y)if x==y then return x..y;end;return x.."-"..y;end)s=s:gsub("ck"..v,"ck-%1")s=s:gsub(v.."y"..v,"%1y-%2")for b=1,2 do
s=s:gsub(v.."([^aeiou\-]?)([^aeiou\-]+)"..v,"%1%2-%3%4")end
end
io.write(s)end

Non golfé

function checkEquals(x,y)
    if x==y then 
        return x..y
    end
    return x.."-"..y
end
i=io.read()
v="([aeiou])"
for s in i:gfind("%l+ ?") do
    if s:len()~=4 then
        s=s:gsub(v..v,checkEquals)
        s=s:gsub("ck"..v,"ck-%1")
        s=s:gsub(v.."y"..v,"%1y-%2")
        for b=1,2 do
            s=s:gsub(v.."([^aeiou\-]?)([^aeiou\-]+)"..v,"%1%2-%3%4")
        end
    end
    io.write(s)
end

Testez-le ici: http://ideone.com/g57TzA

Lien
la source
Je n'ai pas de rubis, mais ça semble bien en effet.
seequ
4

Bash + coreultils, 173 octets

Je pense que j'ai tous les derniers changements de règles:

v=aeiou
r="[$v])/\1-\2/g"
s=s/\([$v]
e="$s[^$v-])([^$v-]+$r
"
tr \  \\n|sed -r "/^([a-z]{4}|[^$v]*[$v][^$v]*)$/bx
$s)($r
${s}ck)($r
$e$e${s}y)($r
$s)([^$v-]$r
:x"|tr \\n \ 

Notez que le dernier caractère de la dernière ligne est un (espace).

Je pense que cela satisfait suffisamment "illisible et non maintenable" ;-)

Prend l'entrée de STDIN.

Substitution de regex principalement droite. La première ligne de l' sedexpression correspond aux règles 1 et 2, puis passe simplement à l' :xétiquette à la fin de l'expression.

Les trs au début et à la fin du pipeline séparent les mots de la nouvelle ligne, ils sont donc plus faciles sedà gérer. J'espérais faire et tous sedrépondre, mais cette façon est plus simple et plus facile.

Exemple:

$ ./sylabify.sh <<< "diaspora nickel sister dragon hello world have a nice day pour some nickel and xenon there paying tricks quicksilver"
di-as-po-ra nick-el sis-ter dra-gon hel-lo world have a nice day pour some nick-el and xe-non the-re pay-ing tricks qu-ic-ksil-ver $ 
Traumatisme numérique
la source
Argh, j'oublie toujours que la règle # 3 a changé. C'est bon.
seequ