Convertir singular a plural

27

Hay dos formas de sustantivos, singular y plural. La conversión entre estos dos es bastante fácil.

  1. Normalmente, lo terminas con s. ex. car=> cars.

  2. Si termina con s, x, z, cho sh, al final con es. ex. bus=> buses.

  3. Si termina con yuna consonante justo antes, cambie ya ies. ex. penny=> pennies.

  4. Si termina con fo fe, cámbielo a ves. ex. knife=> knives.

  5. Si termina con ouna consonante justo antes, cámbiela a oes. ex. potato=> potatoes.


Tarea

Se le dará un sustantivo singular. Tienes que convertir el sustantivo dado a plural y generarlo.


Reglas

  • No se le darán sustantivos irregulares, como mousey moose.

  • No se le darán excepciones, como safe( safes; violar # 4), piano( pianos; violar # 5) y o( oes, violar # 5).

  • No se le darán palabras que tengan dos o más formas plurales posibles, como mosquito( mosquitoso mosquitoes) y roof( roofso rooves).

  • No se le darán sustantivos incontables.

  • y no cuenta como vocal.


Ejemplos

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
Matthew Roh
fuente
Pregunta editada para mayor claridad. Siéntase libre de retroceder.
JungHwan Min
11
Ahh, inglés - un montón de reglas arbitrarias y casos especiales :)
Esolanging Fruit
38
@ Challenger5 Sí, pero puedes entenderlo a través de pensamientos duros y exhaustivos. ;)
JungHwan Min
@MatthewRoh He editado la consonante en la regla frontal para que quede más clara. También se agregaron un par de casos de prueba para lo mismo. Si no he entendido bien, edítelo para aclararlo.
ghosts_in_the_code
2
@ Challenger5 Si compara el inglés con el holandés, apenas existen reglas. El holandés tiene reglas y casos especiales, y casos especiales que contradicen esos casos especiales, y en algunos casos incluso casos especiales que contradicen esos casos especiales que esos casos especiales contradicen. ;)
Kevin Cruijssen

Respuestas:

46

Mathematica, 9 bytes

Pluralize

Sí, hay una función incorporada para esto.

Salida de muestra

Pluralize["car"]

cars

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

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

JungHwan Min
fuente
66
Waaaaaat! ¿Hay algo para lo que Mathematica no tenga incorporado?
KeyWeeUsr
2
D: Builtins también han atacado este desafío
Matthew Roh
18

Retina , 57 53 56 55 58 57 bytes

Gracias a MartinEnder por algunas sugerencias de golf.

Gracias a BusinessCat por jugar al golf 1 byte

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

Pruébalo en línea!

Explicación (obsoleta)

([^aeiou])y$
$1ie

Cambios {consonant}ya{consonant}ie

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

Añade un nuevo ecuando la palabra termina con una {consonant}o, f, x, z, s, sho ch.

fe$
ve

Cambia un final feave

$
s

Finalmente agregue un sa la palabra.

Ediciones

  • Bytes agregados porque olvidé la segunda regla
  • Se agregaron bytes para actualizar eyecomo ejemplo
Kritixi Lithos
fuente
1
Lo siento si esta es una pregunta estúpida, no he usado Retina. ¿Por qué se necesitan los corchetes en la primera línea?
user2390246
No importa, creo que he respondido mi propia pregunta. Se debe a la referencia al pasado en la siguiente línea.
user2390246
Sí, es porque queremos capturar al personaje antes de yusarlo$1
Kritixi Lithos
Creo que lo tengo en 57 bytes: Pruébelo en línea
Business Cat
16

JavaScript (ES6),  109  97 bytes

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

Pruébalo en línea!

Arnauld
fuente
¿Por qué tienes un ()frente fe?
Kodos Johnson
1
@KodosJohnson Todas las replace()iteraciones incluyen una referencia al primer grupo coincidente (con $1). Por eso necesito un grupo coincidente vacío aquí.
Arnauld
¿Lo has intentado (?<![aeiou])y?
Titus
@Titus Desafortunadamente, JS no implementa aserciones secundarias.
Arnauld
11

Lote, 325 bytes

@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
fuente
¿Qué pasa @echo offal principio en lugar de en @todas partes? Además, @set/ps=parece un poco oxidado de un teléfono. ¿La svariable no aceptará los valores de corte de todos modos?
KeyWeeUsr
@KeyWeeUsr @echo offya tiene 9 bytes sin la nueva línea, por lo que no me ahorra nada. Además, @set/ps=es necesario ingresar el valor en primer lugar.
Neil
7

Haskell, 216 207 205 bytes

¡Gracias a @Lynn, @ user1472751 y @Laikoni por la ayuda!

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"

Legible

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"

Explicación

import Data.Listpara la función isSuffixOf. endsWithOneOf( en la versión golfizada) devuelve si uno de los elementos de la lista es un final de la cadena. consonants(c)es solo una lista de todas las consonantes.

Finalmente, pluralize(p)verifica las terminaciones y devuelve la pluralización adecuada.

Ejemplo:

p "potato" == "potatoes"
Eisfunke
fuente
1
Buena solución! Tiene 216 caracteres , pero tiene varios bytes, lo que hace que su solución sea de 226 bytes. (Los desafíos de golf de código se puntúan explícitamente en bytes, porque contar caracteres te permite hacer trampas a veces). !¡Sin embargo, puedes cambiarle el nombre ! Además, words"s x z ch sh"ahorra 5 bytes. Eliminando parens (map(:"o")c))y (map(:"y")c))ahorra 4 más.
Lynn
Gracias por la ayuda, @ Lynn! Implementé tus sugerencias.
Eisfunke
2
Puede guardar un byte utilizando c=['b'..'z']\\"eiou"ya 'a'que siempre se elimina.
user1472751
1
0<1es un byte más corto que True. Además, las nuevas líneas tienen el mismo número de bytes ;pero hacen que el código de golf sea un poco mejor legible.
Laikoni
5

Perl, 66 + 2 ( -plbandera) = 68 bytes

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

Utilizando:

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

Pruébalo en Ideone.

Denis Ibaev
fuente
5

Röda , 80 bytes

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

La función modifica su argumento. Uso: main word { f word; print word }Aquí hay una versión que usa un valor de retorno (83 bytes):

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

Y a continuación hay una función que lee infinitos valores del flujo de entrada y empuja formas plurales al flujo de salida ( 87 83 bytes):

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

Es una función anónima, ya que es más corta que crear una función con nombre.

fergusq
fuente
¿Cómo se muestra el resultado de la primera función (la que comienza con f&s)? Simplemente f("word")no parece mostrar nada
Kritixi Lithos
@KritixiLithos El parámetro es una referencia, por lo que el argumento debe ser una variable.
fergusq
5

PHP, 103 100 bytes

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

Pruébalo en línea!

La preg_replacefunción incluye una variedad de patrones y reemplazos.

  • Guardado 2 bytes gracias a Titus.
  • Guardado 1 byte gracias a Dewi Morgan.
Kodos Johnson
fuente
2
Creo que puede guardar un byte con -Ry $argn. Y usar una aserción con yguardar dos: (?<![aeiou])y$permite iecomo reemplazo: no \1, sin comillas.
Titus
1
Otro byte de([^aeiou]o|sh?|x|z|ch)$
Dewi Morgan
@Titus En realidad, parece que hay una penalización de 1 byte por usar -R(pero no -r) para que eso no cambie el conteo de bytes, desafortunadamente. Pero la sugerencia retrospectiva funciona muy bien. Gracias.
Kodos Johnson
4

Pitón 3, 271 239 199 bytes

¡Gracias a @ovs por reducirlo en 72 bytes!

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"

Pruébalo en línea!

numbermaniac
fuente
1
Puede eliminar algunos espacios en blanco innecesarios y combinar el primero y el último elif. Las listas de caracteres individuales se pueden reemplazar por cadenas. Cambiar a python ahorra 3 bytes adicionales. tio
ovs
@ovs Hecho, gracias! elifSin embargo, no combiné el s, porque ese medio se potatoconvierte en potaties.
numbermaniac
1
Miré en la línea equivocada;). Puedes combinar el if con el último elif. Para guardar algunos bytes más, reemplace la última línea con print(s+"s")y elimine el caso else también cada s que esté agregando a la palabra. Tio
ovs
1
Cuando reemplaza su lógica if / elif con and/*y or/+y realiza una función lambda sin nombre, puede obtenerla en menos de 200 bytes (
cambié
@ovs Ooh, eso print(s+"s")es inteligente. Todo ha cambiado; prácticamente reescribiste todo el asunto jajaja. ¡Gracias! (Ni siquiera sabía que podías hacer True and "string"eso)
numbermaniac
2

sed, 70 79 bytes

69 78 + 1 para bandera -E(BSD) / -r(GNU)

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

Puerto directo de la respuesta de retina .

Kevin
fuente
2

Pip , 63 61 bytes

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

Tan cerca de atrapar Retina! Pero probablemente no va a suceder. :(

Pruébalo en línea!

Explicación

Estrategia básica: Replace realiza varios reemplazos uno tras otro cuando se le dan listas de patrones y reemplazos. Queremos hacer los siguientes reemplazos:

  • (sh?|x|z|ch)$ -> agregar un e
  • [^aeiou]y-> cambie el ya iy agregue une
  • fe?-> cambiar vy agregar une
  • [^aeiou]o -> agregar un e

Entonces queremos abordar un sindependientemente.

Trucos:

  • El Coperador, dado un regex, lo envuelve en un grupo de captura; C`xyz`es un byte más corto que `(xyz)`.
  • Se puede crear una lista de expresiones regulares o reemplazos que terminen con el mismo carácter concatenando el carácter a la lista en lugar de incluirlo en todos los elementos. La concatenación de un escalar (cadena) a un patrón (expresión regular / reemplazo) coacciona a un patrón.
  • En lugar de concatenar el s(y tener que lidiar con el orden de precedencia de Ry .), podemos simplemente Opronunciar la parte principal de la palabra y luego imprimirla por sseparado.

Código espaciado y comentado:

                  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
fuente
2

C #, 73 163 bytes:

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

Sí, otro idioma con él incorporado (aunque debe agregar una referencia a System.Data.Entity.Design.dll)

Usar:

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

Salida:

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
RoadieRich
fuente
Bienvenido al sitio. ¿Cómo ejecuto este código?
Wheat Wizard
@WheatWizard actualizado. ¿Debería haber incluido más detalles (usando declaraciones, etc.) en el recuento de bytes?
RoadieRich
Curiosamente, el reverso de esto (Singularize) falla en algunos casos de prueba simples. Por ejemplo, está convencido de que el singular de "cursos" es "cours".
Morgan Thrapp
Creo que los espacios de nombres deben incluirse en el recuento de bytes de este, especialmente dado que no es uno de los "normales". Pero creo que también necesita al menos envolver esto en una lambda, pasando el argumento al método. Como es esto, es solo un grupo de métodos
pinkfloydx33
@ pinkfloydx33 mejor ahora?
RoadieRich
2

Python 199 187 176 Bytes

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
fuente
2

Rails runner, 18 bytes

$><<gets.pluralize

Ejemplo:

$ echo knife | rails r filename.rb
knives
SztupY
fuente
Ahora que es un lenguaje esotérico.
Ven
2

Python, 296 bytes

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')
just_floating
fuente
0

Puerto directo de Retina:

Ruby , 111 bytes

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

Pruébalo en línea!

Invoque a través de ruby -lpey proporcione un archivo como input.txtpara el primer argumento CLI.

stephanmg
fuente
Probablemente puede ser más "golf". Por cierto: ¿Se pueden agregar archivos a TIO?
stephanmg
0

C, 321 bytes

#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;}

prueba:

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

resultados:

[car] [cars]
[bus] [buses]
[potato] [potatoes]
[knife] [knives]
[penny] [pennies]
[exception] [exceptions]
[wolf] [wolves]
[eye] [eyes]
[decoy] [decoys]
[radio] [radios]
[radio] [radios]
RosLuP
fuente
Debe ser wolvesno wolfves.
mbomb007
@ceilingcat ¿qué pasa con "static C r [256], / * Z =" aeiou ", i = 0, w, n;" en lugar de "static C r [256]; C / * Z =" aeiou ", i = 0, w, n;"?
RosLuP
1
260 bytes
ceilingcat
-1

Java 7, 408 bytes

Golfizado:

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

Básicamente probando cuál es el final de la cadena y agregando / reemplazando letras dependiendo de qué caso sea. El booleano y la cadena al principio son solo para eliminar la repetición en los casos de prueba y hacer que el código sea más pequeño.

Versión legible:

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";
}
Mella
fuente
66
No puedes usar un fragmento.
Okx