Converter singular em plural

27

Existem duas formas de substantivos, singular e plural. A conversão entre esses dois é bastante fácil.

  1. Normalmente, você termina com s. ex. car=> cars.

  2. Se ele termina com s, x, z, chou sh, terminá-la com es. ex. bus=> buses.

  3. Se terminar com yuma consoante logo antes, altere ypara ies. ex. penny=> pennies.

  4. Se terminar com fou fe, mude para ves. ex. knife=> knives.

  5. Se terminar com ouma consoante logo antes, mude para oes. ex. potato=> potatoes.


Tarefa

Você receberá um substantivo singular. Você precisa converter o substantivo fornecido para o plural e produzi-lo.


Regras

  • Você não receberá substantivos irregulares, como mousee moose.

  • Você não receberá exceções, como safe( safes; violar # 4), piano( pianos; violar # 5) e o( oes, violar # 5).

  • Você não receberá palavras com duas ou mais formas plurais possíveis, como mosquito( mosquitosou mosquitoes) e roof( roofsou rooves).

  • Você não receberá substantivos incontáveis.

  • y não conta como vogal.


Exemplos

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
Matthew Roh
fonte
Pergunta editada para maior clareza. Sinta-se livre para reverter.
JungHwan Min
11
Ahh, Inglês - uma enorme pilha de regras arbitrárias e casos especiais :)
Esolanging Fruit
38
@ Challenger5 Sim, mas você pode entendê-lo através de pensamentos profundos e difíceis. ;)
JungHwan Min
@ MatthewRoh Eu editei a consoante na regra da frente para torná-la mais clara. Também foram adicionados alguns casos de teste para o mesmo. Se eu entendi errado, edite-o para esclarecer.
ghosts_in_the_code
2
@ Challenger5 Se você comparar o inglês ao holandês, quase não existem regras. O holandês possui regras e casos especiais, e casos especiais que contradizem esses casos especiais e, em alguns casos, até casos especiais que contradizem esses casos especiais que esses casos especiais contradizem. ;)
Kevin Cruijssen

Respostas:

46

Mathematica, 9 bytes

Pluralize

Sim, há um built-in para isso!

Saída de amostra

Pluralize["car"]

cars

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

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

JungHwan Min
fonte
6
Waaaaaat! Existe algo para o qual o Mathematica não tem built-in?
KeyWeeUsr
2
D: Builtins também atacaram este desafio #
Matthew Roh
18

Retina , 57 53 56 55 58 57 bytes

Obrigado a MartinEnder por algumas sugestões de golfe

Graças ao BusinessCat por jogar golfe com 1 byte

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

Experimente online!

Explicação (desatualizada)

([^aeiou])y$
$1ie

Alterações {consonant}yem{consonant}ie

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

Acrescenta um epara quando as extremidades da palavra com um {consonant}o, f, x, z, s, shou ch.

fe$
ve

Muda um final feparave

$
s

Por fim, acrescente um sà palavra.

Edições

  • Adicionados bytes porque esqueci a segunda regra
  • Adicionados bytes para atualização eyecomo um exemplo
Kritixi Lithos
fonte
1
Desculpe se esta é uma pergunta estúpida, eu não usei Retina. Por que os colchetes são necessários na primeira linha?
user2390246
Não importa, acho que respondi minha própria pergunta. É por causa da referência de lookback na linha a seguir.
user2390246
Sim, é porque queremos capturar o personagem antes do yuso$1
Kritixi Lithos 6/17/17
Eu acho que eu entendi em 57 bytes: Experimente on-line
gato do negócio
16

JavaScript (ES6),  109  97 bytes

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

Experimente online!

Arnauld
fonte
Por que você tem um ()na frente fe?
Kodo Johnson
1
@KodosJohnson Todas as replace()iterações incluem uma referência ao primeiro grupo correspondente (com $1). É por isso que preciso de um grupo de correspondência vazio aqui.
Arnauld
Você já tentou (?<![aeiou])y?
Titus
@Titus Infelizmente, o JS não implementa asserções lookbehind.
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
fonte
Que tal @echo offno começo e não em @todo lugar? Além disso, @set/ps=parece um pouco enferrujado de um telefone. A svariável não aceitará os valores de fatia de qualquer maneira?
KeyWeeUsr #
O @KeyWeeUsr @echo offjá tem 9 bytes sem a nova linha, portanto, não me salva nada. Além disso, @set/ps=é necessário inserir o valor em primeiro lugar.
Neil
7

Haskell, 216 207 205 bytes

Obrigado a @Lynn, @ user1472751 e @Laikoni pela ajuda!

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"

Legível

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"

Explicação

import Data.Listpara a função isSuffixOf. endsWithOneOf( na versão golfed) retorna se um dos elementos da lista é um final da string. consonants(c)é apenas uma lista de todas as consoantes.

Finalmente, pluralize(p)verifica as terminações e retorna a pluralização adequada.

Exemplo:

p "potato" == "potatoes"
Eisfunke
fonte
1
Ótima solução! São 216 caracteres , mas têm vários bytes, tornando sua solução 226 bytes. (Os desafios de código de golfe são pontuados explicitamente em bytes, porque a contagem de caracteres permite trapacear algumas vezes.) !Porém, você pode renomeá-lo ! Além disso, words"s x z ch sh"salva 5 bytes. Remover parens ao redor (map(:"o")c))e (map(:"y")c))economiza mais 4.
Lynn
Obrigado pela ajuda, @Lynn! Eu implementei suas sugestões.
9788 Eisenhunke #
2
Você pode salvar um byte usando c=['b'..'z']\\"eiou"uma vez que 'a'é sempre removido.
user1472751
1
0<1é um byte menor que True. As novas linhas também têm a mesma contagem de bytes, ;mas tornam o código golfado um pouco mais legível.
Laikoni 7/03
5

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

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

Usando:

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

Experimente em Ideone.

Denis Ibaev
fonte
5

Röda , 80 bytes

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

A função modifica seu argumento. Uso: main word { f word; print word }Aqui está uma versão que usa um valor de retorno (83 bytes):

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

E abaixo está uma função que lê infinitamente muitos valores do fluxo de entrada e empurra formas plurais para o fluxo de saída ( 87 83 bytes):

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

É uma função anônima, pois é mais curta que a criação de uma função nomeada.

fergusq
fonte
Como você exibe o resultado da primeira função (a que começa com f&s)? Simplesmente f("word")não parece exibir qualquer coisa
Kritixi Lithos
@KritixiLithos O ​​parâmetro é uma referência, portanto o argumento deve ser uma variável.
Fergusq 5/03
5

PHP, 103 100 bytes

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

Experimente online!

A preg_replacefunção recebe uma matriz de padrões e substituições.

  • Economizou 2 bytes graças a Titus.
  • Guardado 1 byte graças a Dewi Morgan.
Kodos Johnson
fonte
2
Eu acho que você pode salvar um byte com -Re $argn. E usar uma asserção com ysalva dois: (?<![aeiou])y$permite iecomo substituição: não \1, sem aspas.
Titus
1
Outro byte de([^aeiou]o|sh?|x|z|ch)$
Dewi Morgan 6/17
@Titus Na verdade, parece que existe uma penalidade de 1 byte pelo uso -R(mas não -r), para que isso não mude a contagem de bytes, infelizmente. Mas a sugestão lookbehind funciona muito bem. Obrigado.
Kodo Johnson
4

Python 3, 271 239 199 bytes

Obrigado ao @ovs por reduzi-lo em 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"

Experimente online!

numbermaniac
fonte
1
Você pode remover alguns espaços em branco desnecessários e combinar o primeiro e o último elif. As listas de caracteres únicos podem ser substituídas por seqüências de caracteres. Mudar para python economiza 3 bytes adicionais. tio
ovs 6/03/2017
@ovs Feito, obrigado! Eu não combinei os elifs no entanto, porque isso significa que potatose torna potaties.
numbermaniac
1
Eu olhei na linha errada;). Você pode combinar o if com o último elif. Para economizar mais bytes, substitua a última linha por print(s+"s")e remova o caso else, todos os s que você está anexando à palavra. Tio
ovs 6/03/03
1
Ao substituir a lógica if / elif com and/*e or/+e fazer uma função lambda sem nome você pode obtê-lo menos de 200 bytes (eu troquei os casos um pouco)
OVS
@ovs Ooh, isso print(s+"s")é inteligente. Tudo mudou; você praticamente reescreveu a coisa toda, lol. Obrigado! (Eu nem sabia que você poderia fazer True and "string"assim)
numbermaniac
2

sed, 70 79 bytes

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

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

Porta direta da resposta da retina .

Kevin
fonte
2

Pip , 63 61 bytes

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

Tão perto de pegar Retina! Mas provavelmente não vai acontecer. :(

Experimente online!

Explicação

Estratégia básica: o Replace executa várias substituições, uma após a outra, quando são fornecidas listas de padrões e substituições. Queremos fazer as seguintes substituições:

  • (sh?|x|z|ch)$ -> adicione um e
  • [^aeiou]y-> mude ypara ie adicione ume
  • fe?-> mude para ve adicione ume
  • [^aeiou]o -> adicione um e

Então queremos abordar de forma sindependente.

Truques:

  • O Coperador, dado um regex, agrupa-o em um grupo de captura; C`xyz`é um byte menor que `(xyz)`.
  • Uma lista de regexes ou substituições que terminam com o mesmo caractere pode ser criada concatenando-o à lista em vez de incluí-lo em todos os itens. A concatenação de um escalar (string) para um padrão (regex / substituição) coage para um padrão.
  • Em vez de concatenar o s(e ter que lidar com a ordem de precedência de Re .), podemos simplesmente Outilizar a parte principal da palavra e depois imprimir a sseparadamente.

Código espaçado e 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
fonte
2

C #, 73 163 bytes:

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

Sim, outro idioma com ele embutido (embora você precise adicionar uma referência 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}");
}

Saída:

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
RoadieRich
fonte
Bem vindo ao site. Como executo esse código?
Assistente de trigo
@WheatWizard atualizado. Devo ter incluído mais detalhes (usando instruções etc.) na contagem de bytes?
RoadieRich
Curiosidades interessantes, o inverso disso (Singularize) falha em alguns casos de teste simples. Por exemplo, está convencido de que o singular de "cursos" é "cours".
Morgan Thrapp
Acho que os namespaces precisam ser incluídos na contagem de bytes deste, especialmente porque não é um dos 'normais'. Mas acho que você também precisa pelo menos agrupar isso em um lambda, passando o argumento para o método Como é que isto é apenas um grupo de método
pinkfloydx33
@ pinkfloydx33 melhor agora?
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
fonte
2

Corredor de trilhos, 18 bytes

$><<gets.pluralize

Exemplo:

$ echo knife | rails r filename.rb
knives
SztupY
fonte
Agora essa é uma linguagem esotérica.
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
fonte
0

Porto direto da Retina:

Ruby , 111 bytes

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

Experimente online!

Chame ruby -lpee forneça um arquivo como input.txtno primeiro argumento da CLI.

stephanmg
fonte
Provavelmente pode ser mais 'jogado'. Btw .: Pode-se adicionar arquivos ao TIO?
stephanmg 3/12
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;}

teste:

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
fonte
Deve ser wolvesnão wolfves.
mbomb007
@ceilingcat e quanto a "estática C r [256], / * Z =" aeiou ", i = 0, w, n;" no lugar de "estático C r [256]; C / * Z =" aeiou ", i = 0, w, n;"?
RosLuP 04/12
1
260 bytes
ceilingcat
-1

Java 7, 408 bytes

Golfe:

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

Testando basicamente qual é o final da String e adicionando / substituindo letras, dependendo do caso. O booleano e String no início são apenas para remover a repetição nos casos de teste e diminuir o código.

Versão legível:

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";
}
usuario
fonte
6
Você não pode usar um trecho.
Okx 06/03/19