Convertir le singulier au pluriel

27

Il existe deux formes de noms, singulier et pluriel. La conversion entre ces deux est assez facile.

  1. Normalement, vous y mettez fin s. ex. car=> cars.

  2. Si elle se termine par s, x, z, chou sh, fin avec es. ex. bus=> buses.

  3. S'il se termine par yune consonne juste avant, changez le ypar ies. ex. penny=> pennies.

  4. S'il se termine par fou fe, remplacez-le par ves. ex. knife=> knives.

  5. S'il se termine par oune consonne juste avant, changez-la en oes. ex. potato=> potatoes.


Tâche

Vous recevrez un nom singulier. Vous devez convertir le nom donné au pluriel et le sortir.


Règles

  • Vous ne recevrez pas de noms irréguliers, comme mouseet moose.

  • Vous ne recevrez pas d'exceptions, telles que safe( safes; violation # 4), piano( pianos; violation # 5) et o( oes, violation # 5).

  • Vous ne recevrez pas de mots qui ont deux ou plusieurs formes plurielles possibles, telles que mosquito( mosquitosou mosquitoes) et roof( roofsou rooves).

  • On ne vous donnera pas de noms innombrables.

  • y ne compte pas comme une voyelle.


Exemples

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
Matthew Roh
la source
Question modifiée pour plus de clarté. N'hésitez pas à revenir en arrière.
JungHwan Min
11
Ahh, anglais - une énorme pile de règles arbitraires et de cas spéciaux :)
Esolanging Fruit
38
@ Challenger5 Oui, mais vous pouvez le comprendre à travers des pensées approfondies et dures. ;)
JungHwan Min
@MatthewRoh J'ai édité la consonne devant la règle pour la rendre plus claire. A également ajouté quelques cas de test pour le même. Si j'ai mal compris, veuillez le modifier pour clarifier.
ghosts_in_the_code
2
@ Challenger5 Si vous comparez l'anglais au néerlandais, il n'y a pratiquement pas de règles du tout. ;)
Kevin Cruijssen

Réponses:

46

Mathematica, 9 octets

Pluralize

Oui, il y a une fonction intégrée pour cela!

Exemple de sortie

Pluralize["car"]

cars

Pluralize /@ {"bus", "potato", "knife", "penny", "exception", "wolf", "eye"}

{"buses", "potatoes", "knives", "pennies", "exceptions", "wolves", "eyes"}

JungHwan Min
la source
6
Waaaaaat! Y a-t-il quelque chose que Mathematica n'a pas intégré?
KeyWeeUsr
2
D: Builtins a également attaqué ce défi
Matthew Roh
18

Rétine , 57 53 56 55 58 57 octets

Merci à MartinEnder pour quelques suggestions de golf

Merci à BusinessCat pour avoir joué au golf 1 octet

([^aeiou]o|sh?|ch|z|x)$
$1e
fe?$
ve
([^aeiou])y$
$1ie
$
s

Essayez-le en ligne!

Explication (obsolète)

([^aeiou])y$
$1ie

Modifications apportées {consonant}yà{consonant}ie

([^aeiou]o|[fxzs]|[sc]h)$
$&e

Ajoute un equand les extrémités de mots avec un {consonant}o, f, x, z, s, shou ch.

fe$
ve

Remplace une fin feparve

$
s

Enfin, ajoutez un sau mot.

Modifications

  • Octets ajoutés car j'ai oublié la deuxième règle
  • Octets ajoutés pour mettre à jour avec eyecomme exemple
Kritixi Lithos
la source
1
Désolé si c'est une question stupide, je n'ai pas utilisé Retina. Pourquoi les crochets ronds sont-ils nécessaires dans la première ligne?
user2390246
Peu importe, je pense avoir répondu à ma propre question. C'est à cause de la référence rétrospective dans la ligne suivante.
user2390246
Oui, c'est parce que nous voulons capturer le personnage avant de l' yutiliser$1
Kritixi Lithos
Je pense que je l'ai eu en 57 octets: Essayez-le en ligne
Business Cat
16

JavaScript (ES6),  109  97 octets

s=>s[R='replace'](/([^aeiou])y$/,'$1ie')[R](/fe?$/,'ve')[R](/([^aeiou]o|[sxz]|[cs]h)$/,'$1e')+'s'

Essayez-le en ligne!

Arnauld
la source
Pourquoi avez-vous un ()devant fe?
Kodos Johnson
1
@KodosJohnson Toutes les replace()itérations incluent une référence au premier groupe correspondant (avec $1). C'est pourquoi j'ai besoin d'un groupe correspondant vide ici.
Arnauld
As-tu essayé (?<![aeiou])y?
Titus
@Titus Malheureusement, JS n'implémente pas les assertions lookbehind.
Arnauld
11

Lot, 325 octets

@set/ps=
@for %%v in (a e i o u)do @(
for %%e in (o y)do @if %s:~-2%==%%v%%e goto s
if %s:~-2%==%%vf set s=%s:~,-1%ve&goto s
if %s:~-3%==%%vfe set s=%s:~,-2%ve&goto s
)
@if %s:~-1%==y set s=%s:~,-1%ie
@for %%e in (o s x z)do @if %s:~-1%==%%e set s=%s%e
@for %%e in (c s)do @if %s:~-2%==%%eh set s=%s%e
:s
@echo %s%s
Neil
la source
Et @echo offau début plutôt que @partout? En outre, @set/ps=semble un peu rouillé par un téléphone. La svariable n'acceptera- t-elle pas les valeurs de découpage de toute façon?
KeyWeeUsr
@KeyWeeUsr @echo offest déjà 9 octets sans la nouvelle ligne, donc cela ne me sauve rien. En outre, @set/ps=est nécessaire pour saisir la valeur en premier lieu.
Neil
7

Haskell, 216 207 205 octets

Merci à @Lynn, @ user1472751 et @Laikoni pour l'aide!

import Data.List
(!)s=or.map(\x->x`isSuffixOf`s)
c=['b'..'z']\\"eiou"
p s|s!(words"s x z ch sh"++map(:"o")c)=s++"es"|s!map(:"y")c=init s++"ies"|s!["f"]=init s++"ves"|s!["fe"]=(init.init)s++"ves"|0<1=s++"s"

Lisible

import Data.List;

endsWithOneOf :: String -> [String] -> Bool
endsWithOneOf str ends = (or . map (\end -> end `isSuffixOf` str)) ends 

consonants :: [Char]
consonants = ['a'..'z'] \\ "aeiou"

pluralize :: String -> String
pluralize str
    | str `endsWithOneOf` (words "s x z ch sh" ++ (map (:"o") consonants)) = str ++ "es"
    | str `endsWithOneOf` (map (:"y") consonants) = init str ++ "ies"
    | str `endsWithOneOf` ["f"] = init str ++ "ves"
    | str `endsWithOneOf` ["fe"] = (init.init) str ++ "ves"
    | otherwise = str ++ "s"

Explication

import Data.Listpour la fonction isSuffixOf. endsWithOneOf( dans la version golfée) renvoie si l'un des éléments de la liste est une fin de la chaîne. consonants(c)est juste une liste de toutes les consonnes.

Enfin, pluralize(p)vérifie les terminaisons et renvoie la pluralisation appropriée.

Exemple:

p "potato" == "potatoes"
Eisfunke
la source
1
Bonne solution! Il s'agit de 216 caractères , mais de plusieurs octets, ce qui fait de votre solution 226 octets. (Les défis de golf de code sont explicitement marqués en octets, car le comptage de caractères vous permet parfois de tricher.) Vous pouvez simplement le renommer !, cependant! Enregistre également words"s x z ch sh"5 octets. Suppression des parens autour (map(:"o")c))et (map(:"y")c))économise 4 de plus.
Lynn
Merci pour l'aide, @Lynn! J'ai mis en œuvre vos suggestions.
Eisfunke
2
Vous pouvez enregistrer un octet en utilisant c=['b'..'z']\\"eiou"car 'a'est toujours supprimé.
user1472751
1
0<1est un octet plus court que True. Les sauts de ligne ont également le même nombre d'octets, ;mais rendent le code joué un peu plus lisible.
Laikoni
5

Perl, 66 + 2 ( -plindicateur) = 68 octets

$_.=/(ch|sh?|x|z|[^aeiou]o)$/+s/([^aeiou])y$/$1i/+s/fe?$/v/?es:"s"

En utilisant:

perl -ple '$_.=/(ch|sh?|x|z|[^aeiou]o)$/+s/([^aeiou])y$/$1i/+s/fe?$/v/?es:"s"' <<< car

Essayez-le sur Ideone.

Denis Ibaev
la source
5

Röda , 80 octets

f&s{s~="([^aeiou])y$","$1ie","([sxz]|[cs]h|[^aeiuo]o)$","$1e","fe?$","ve"s.="s"}

La fonction modifie son argument. Utilisation: main word { f word; print word }voici une version qui utilise une valeur de retour (83 octets):

f s{s~="([^aeiou])y$","$1ie","([sxz]|[cs]h|[^aeiuo]o)$","$1e","fe?$","ve";[s.."s"]}

Et ci-dessous est une fonction qui lit une infinité de valeurs du flux d'entrée et pousse plusieurs formes vers le flux de sortie ( 87 83 octets):

{replace"([^aeiou])y$","$1ie","([sxz]|[cs]h|[^aeiuo]o)$","$1e","fe?$","ve","$","s"}

C'est une fonction anonyme, car elle est plus courte que la création d'une fonction nommée.

fergusq
la source
Comment afficher le résultat de la première fonction (celle commençant par f&s)? f("word")Ne semble tout simplement pas afficher quoi que ce soit
Kritixi Lithos
@KritixiLithos Le paramètre est une référence, donc l'argument doit être une variable.
fergusq
5

PHP, 103 100 octets

<?=preg_replace(['/([^aeiou]o|sh?|x|z|ch)$/','/(?<![aeiou])y$/','/fe?$/'],['\1e',ie,ve],$argv[1]).s;

Essayez-le en ligne!

La preg_replacefonction prend dans un tableau de modèles et de remplacements.

  • Enregistré 2 octets grâce à Titus.
  • Enregistré 1 octet grâce à Dewi Morgan.
Kodos Johnson
la source
2
Je pense que vous pouvez enregistrer un octet avec -Ret $argn. Et l'utilisation d'une assertion avec ysauvegarde deux: (?<![aeiou])y$permet iecomme remplacement: non \1, pas de guillemets.
Titus
1
Un autre octet de([^aeiou]o|sh?|x|z|ch)$
Dewi Morgan
@Titus En fait, il semble qu'il y ait une pénalité de 1 octet pour l'utilisation -R(mais pas -r), ce qui ne modifie malheureusement pas le nombre d'octets. Mais la suggestion de lookbehind fonctionne très bien. Merci.
Kodos Johnson
4

Python 3, 271 239 199 octets

Merci à @ovs de l'avoir réduit de 72 octets!

lambda s,v="aeiou":(s[-2:]=="fe"and s[:-2]+"ve"or s[:-1]+((s[-1]=="y"and s[-2]not in v)*"ie"or s[-1]=="f"and"ve"or s[-1]+((s[-1]in"sxz"or s[-2:]in["ch","sh"])+(s[-1]=="o"and s[-2]not in v))*"e"))+"s"

Essayez-le en ligne!

engourdi
la source
1
Vous pouvez supprimer certains espaces blancs inutiles et combiner le premier et le dernier elif. Les listes de caractères uniques peuvent être remplacées par des chaînes. Le passage à python permet d'économiser 3 octets supplémentaires. tio
ovs
@ovs Terminé, merci! Je n'ai cependant pas combiné les elifs, car cela signifie potatodevient potaties.
numbermaniac
1
J'ai regardé dans la mauvaise ligne;). Vous pouvez combiner le if avec le dernier elif. Pour enregistrer quelques octets supplémentaires, remplacez la dernière ligne par print(s+"s")et supprimez également le cas else tous les s que vous ajoutez au mot. Tio
ovs
1
Lorsque vous remplacez votre logique if / elif par and/*et or/+et créez une fonction lambda sans nom, vous pouvez l'obtenir sous 200 octets (j'ai échangé un peu les cas)
ovs
@ovs Ooh, c'est print(s+"s")intelligent. Tout a changé; vous avez à peu près réécrit le tout lol. Merci! (Je ne savais même pas que tu pouvais faire True and "string"comme ça)
numbermaniac
2

sed, 70 79 octets

69 78 + 1 pour le drapeau -E(BSD) / -r(GNU)

s/([^aeiou])y$/\1ie/
s/([^aeiou]o|[fxzs]|[sc]h)$/&e/
s/fe/ve/
s/$/s/

Port direct de la réponse rétinienne .

Kevin
la source
2

Pip , 63 61 octets

Y`[^aeiou]`OaR[C`sh?|x|z|ch`Cy.'y`fe?`y.'o].'$[_B.'i'v_].'e's

Si près d'attraper la rétine! Mais cela n'arrivera probablement pas. :(

Essayez-le en ligne!

Explication

Stratégie de base: Replace effectue plusieurs remplacements les uns après les autres lorsque des listes de modèles et de remplacements sont fournies. Nous voulons effectuer les remplacements suivants:

  • (sh?|x|z|ch)$ -> ajouter un e
  • [^aeiou]y-> changez le yen iet ajoutez une
  • fe?-> modifier vet ajouter une
  • [^aeiou]o -> ajouter un e

Ensuite, nous voulons aborder un speu importe.

Des trucs:

  • L' Copérateur, étant donné une expression régulière, l'enveloppe dans un groupe de capture; C`xyz`est un octet plus court que `(xyz)`.
  • Une liste d'expressions régulières ou de remplacements qui se terminent tous par le même caractère peut être créée en concaténant le personnage à la liste au lieu de l'inclure dans tous les éléments. La concaténation d'un scalaire (chaîne) à un motif (regex / remplacement) contraint à un motif.
  • Au lieu de concaténer le s(et d'avoir à traiter l'ordre de priorité de Ret .), nous pouvons simplement Oémettre la partie principale du mot puis l'imprimer sséparément.

Code espacé et commenté:

                  a is 1st cmdline input (implicit)
Y`[^aeiou]`       Yank the consonant regex into the y variable
O a R             Output (without newline): a, with the following replacements:
 [                List of regexes to replace:
  C `sh?|x|z|ch`    (sh?|x|z|ch)
  Cy . 'y           ([^aeiou])y
  `fe?`             fe?
  y . 'o            [^aeiou]o
 ] . '$           End of list; concatenate $ to each item
 [                List of replacements:
  _                 Identity function (replace with whole match)
  B                 B is short for {b}, a function returning its second argument; as a
                    callback function for regex replacement, the second argument is
                    the value of capturing group 1 (the consonant before y)
    . 'i            To that, concatenate i
  'v                Scalar literal v
  _                 Identity function
 ] . 'e           End of list; concatenate e to each item
's                Return Scalar literal s, which is autoprinted
DLosc
la source
2

C #, 73 163 octets:

Func<string,string>p=System.Data.Entity.Design.PluralizationServices.PluralizationService.CreateService(System.Globalization.CultureInfo.CurrentCulture).Pluralize

Oui, une autre langue avec elle intégrée (bien que vous deviez ajouter une référence System.Data.Entity.Design.dll)

Utiliser:

var words = new[] { "car", "bus", "potato", "knife", "penny", "exception", "wolf", "eye", "decoy", "radio" };
foreach (var word in words)
{
    var plural = p(word);
    Console.Out.WriteLine($"{word} => {plural}");
}

Sortie:

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
RoadieRich
la source
Bienvenue sur le site. Comment exécuter ce code?
Wheat Wizard
@WheatWizard mis à jour. Aurais-je dû inclure plus de détails (à l'aide d'instructions, etc.) dans le nombre d'octets?
RoadieRich
Petit truc intéressant, l'inverse (Singularize) échoue à quelques cas de test simples. Par exemple, il est convaincu que le singulier des «cours» est «cours».
Morgan Thrapp
Je pense que les espaces de noms doivent être inclus dans le nombre d'octets de celui-ci, d' autant plus qu'il n'est pas l'un des «normaux». Mais je pense que vous devez également au moins envelopper cela dans un lambda, en passant l'argument à la méthode. Comme c'est juste un groupe de méthodes
pinkfloydx33
@ pinkfloydx33 mieux maintenant?
RoadieRich
2

Python 199 187 176 176 octets

lambda s:s+'\bve'*(s[-1]=='f')+'\b\bve'*(s[-2:]=='fe')+'e'*(s[-1]in'sxz'or s[-2:]in('ch','sh')or s[-1]=='o'and s[-2]not in'aiueo')+'\bie'*(s[-1]=='y'and s[-2]not in'aiueo')+'s'
Felipe Nardi Batista
la source
2

Rails runner, 18 octets

$><<gets.pluralize

Exemple:

$ echo knife | rails r filename.rb
knives
SztupY
la source
Voilà un langage ésotérique.
Ven
2

Python, 296 octets

z = input()
if z[-1]in['s','x','z','ch','sh']:print(z+'es')
elif z[-1]=='y'and z[-2]not in['a','e','i','o','u']:print(z[:-1]+'ies')
elif z[-2:]=='fe':print(z[:-2]+'ves')
elif z[-1]=='f':print(z[:-1]+'ves')
elif z[-1]=='o'and z[-2]not in['a','e','i','o','u']:print(z[:-1]+'oes')
else:print(z+'s')
juste_flottant
la source
0

Port direct de Retina:

Rubis , 111 octets

'sub(/([^aeiou])y/){"#{$1}ie"};sub(/(.*)([^aeiou]o|[fxzs]|[sc]h)$/){"#{$1}#{$2}e"};sub(/fe/,"ve");sub(/$/,"s")'

Essayez-le en ligne!

Appelez via ruby -lpeet fournissez un fichier comme input.txtpour le premier argument CLI.

stephanmg
la source
Peut probablement être plus «golfé». Btw .: Peut-on ajouter des fichiers à TIO?
stephanmg
0

C, 321 octets

#define E else if(
#define C unsigned char
C*p(C*b){static C r[999],i,w,n,m;for(n=w=i=0;r[i]=b[i];n=w,w=b[i++]);m=!strchr("aeiou",n);if(strchr("sxz",w)||(w=='h'&&strchr("cs",n))||(w=='o'&&m))r[i++]='e';E'y'==w&&m)r[i-1]='i',r[i++]='e';E'f'==w)r[i-1]='v',r[i++]='e';E'f'==n&&w=='e')r[i-2]='v';r[i++]='s';r[i]=0;return r;}

tester:

C*mx[]={"car","bus","potato","knife","penny","exception","wolf","eye","decoy","radio",0};

main()
{unsigned i;
 for(i=0;mx[i];++i)
    printf("[%s] [%s]\n", mx[i], p(mx[i]));
 return 0;
}

résultats:

[car] [cars]
[bus] [buses]
[potato] [potatoes]
[knife] [knives]
[penny] [pennies]
[exception] [exceptions]
[wolf] [wolves]
[eye] [eyes]
[decoy] [decoys]
[radio] [radios]
[radio] [radios]
RosLuP
la source
Ce ne devrait wolvespas être le cas wolfves.
mbomb007
@ceilingcat qu'en est-il de "statique C r [256], / * Z =" aeiou ", i = 0, w, n;" à la place de "statique C r [256]; C / * Z =" aeiou ", i = 0, w, n;"?
RosLuP
1
260 octets
plafondcat
-1

Java 7, 408 octets

Golfé:

boolean b="bcdfghjklmnpqrstvwxyzs".contains(String.valueOf(s.charAt(s.length()-2))); String x=s.substring(0,s.length()-1);if(s.endsWith("s")||s.endsWith("x")||s.endsWith("z")||s.endsWith("ch")||s.endsWith("sh"))return s+"es";if(s.endsWith("y")&&b)return x+"ies";if(s.endsWith("f")) return x+"ves";if(s.endsWith("fe"))return s.substring(0,s.length()-2)+"ves";if(s.endsWith("o")&&b)return s+"es";return s+="s";

Fondamentalement, tester la fin de la chaîne et ajouter / remplacer des lettres selon le cas. Le booléen et la chaîne au début sont juste pour supprimer la répétition dans les cas de test et rendre le code plus petit.

Version lisible:

public static String pluralize(String s){

// Consonant at the 2nd last position?
boolean b = "bcdfghjklmnpqrstvwxyzs".contains(String.valueOf(s.charAt(s.length()-2))); 

// Substring for cases where last letter needs to be replaced
String x = s.substring(0,s.length()-1);

if(s.endsWith("s") || s.endsWith("x") || s.endsWith("z") || s.endsWith("ch") || s.endsWith("sh"))
    return s + "es";
if(s.endsWith("y") && b)
    return x + "ies";
if(s.endsWith("f")) 
    return x + "ves";
if(s.endsWith("fe"))
    return s.substring(0,s.length()-2) + "ves";
if(s.endsWith("o") && b)
    return s + "es";

return s += "s";
}
Entaille
la source
6
Vous ne pouvez pas utiliser d'extrait.
Okx