Converti singolare in plurale


27

Esistono due forme di sostantivi, singolare e plurale. La conversione tra questi due è abbastanza semplice.

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

  2. Se si finisce con s, x, z, cho sh, terminare con es. ex. bus=> buses.

  3. Se termina con yuna consonante appena prima, cambia yin ies. ex. penny=> pennies.

  4. Se termina con fo fe, cambiarlo in ves. ex. knife=> knives.

  5. Se termina con ouna consonante appena prima di essa, cambiarla in oes. ex. potato=> potatoes.


Compito

Ti verrà dato un nome singolare. Devi convertire il nome dato in plurale ed emetterlo.


Regole

  • Non ti verranno dati nomi irregolari, come mousee moose.

  • Non ti verranno date eccezioni, come safe( safes; violazione del n. 4), piano( pianos; violazione del n. 5) e o( oes, violazione del n. 5).

  • Non ti verranno date parole che hanno due o più possibili forme plurali, come mosquito( mosquitoso mosquitoes) e roof( roofso rooves).

  • Non ti verranno dati nomi innumerevoli.

  • y non conta come una vocale.


Esempi

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios

Domanda modificata per chiarezza. Sentiti libero di tornare indietro.
JungHwan Min

11
Ahh, inglese - un enorme mucchio di regole arbitrarie e casi speciali :)
Esolanging Fruit

38
@ Challenger5 Sì, ma puoi capirlo attraverso pensieri approfonditi e difficili. ;)
JungHwan Min

@MatthewRoh Ho modificato la consonante in primo piano per renderlo più chiaro. Aggiunti anche un paio di casi di test per lo stesso. Se ho frainteso, si prega di modificarlo per chiarire.
ghosts_in_the_code il

2
@ Challenger5 Se si confronta l'inglese con l'olandese non ci sono quasi regole. L'olandese ha regole e casi speciali e casi speciali che contraddicono quei casi speciali, e in alcuni casi anche casi speciali che contraddicono quei casi speciali che quei casi speciali contraddicono. ;)
Kevin Cruijssen il

Risposte:


46

Mathematica, 9 byte

Pluralize

Sì, c'è un built-in per questo!

Uscita campione

Pluralize["car"]

cars

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

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


6
Waaaaaat! C'è qualcosa per cui Mathematica non è integrata?
KeyWeeUsr

2
D: Anche i builtin hanno attaccato questa sfida
Matthew Roh,


18

Retina , 57 53 56 55 58 57 byte

Grazie a MartinEnder per alcuni suggerimenti sul golf

Grazie a BusinessCat per il golf 1 byte

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

Provalo online!

Spiegazione (obsoleta)

([^aeiou])y$
$1ie

Modifiche {consonant}ya{consonant}ie

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

Accoda un equando la parola estremità con un {consonant}o, f, x, z, s, sho ch.

fe$
ve

Cambia un finale feinve

$
s

Infine aggiungi un salla parola.

Le modifiche

  • Byte aggiunti perché ho dimenticato la seconda regola
  • Aggiunti byte con cui aggiornare eyecome esempio

1
Scusa se questa è una domanda stupida, non ho usato Retina. Perché le parentesi tonde sono necessarie nella prima riga?
user2390246

Poco male, penso di aver risposto alla mia domanda. È a causa del riferimento di ricerca nella riga seguente.
user2390246

Sì, è perché vogliamo catturare il personaggio prima ydell'uso$1
Kritixi Lithos il

Penso di averlo ottenuto in 57 byte: provalo online
Business Cat

16

JavaScript (ES6),  109  97 byte

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

Provalo online!


Perché hai un ()davanti fe?
Kodos Johnson,

1
@KodosJohnson Tutte le replace()iterazioni includono un riferimento al primo gruppo corrispondente (con $1). Ecco perché ho bisogno di un gruppo di corrispondenza vuoto qui.
Arnauld

Ci hai provato (?<![aeiou])y?
Tito

@Titus Sfortunatamente, JS non implementa asserzioni lookbehind.
Arnauld

11

Lotto, 325 byte

@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

Che dire @echo offall'inizio piuttosto che @ovunque? Inoltre, @set/ps=sembra un po 'arrugginito da un telefono. La svariabile non accetta comunque i valori di slicing?
KeyWeeUsr

@KeyWeeUsr @echo offè già 9 byte senza la nuova riga, quindi non mi salva nulla. Inoltre, @set/ps=è necessario inserire il valore in primo luogo.
Neil

7

Haskell, 216 207 205 byte

Grazie a @Lynn, @ user1472751 e @Laikoni per l'aiuto!

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"

Leggibile

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"

Spiegazione

import Data.Listper la funzione isSuffixOf. endsWithOneOf( nella versione golfed) restituisce se uno degli elementi della lista è una fine della stringa. consonants(c)è solo un elenco di tutte le consonanti.

Infine, pluralize(p)controlla i finali e restituisce la corretta pluralizzazione.

Esempio:

p "potato" == "potatoes"

1
Bella soluzione! Questo è di 216 caratteri , ma è lungo più byte, rendendo la soluzione di 226 byte. (Le sfide del code golf sono espressamente segnate in byte, perché contare i personaggi ti consente di imbrogliare a volte.) !Tuttavia, puoi semplicemente rinominarlo ! Inoltre, words"s x z ch sh"salva 5 byte. Rimozione di parentesi (map(:"o")c))e ne (map(:"y")c))salva altri 4.
Lynn

Grazie per l'aiuto, @Lynn! Ho implementato i tuoi suggerimenti.
Eisfunke,

2
È possibile salvare un byte utilizzando c=['b'..'z']\\"eiou"poiché 'a'è sempre rimosso.
user1472751

1
0<1è un byte più corta True. Anche i newline hanno lo stesso numero di byte ;ma rendono il codice golfizzato un po 'più leggibile.
Laikoni

5

Perl, 66 + 2 ( -plflag) = 68 byte

$_.=/(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

Provalo su Ideone.


5

Röda , 80 byte

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

La funzione modifica il suo argomento. Utilizzo: main word { f word; print word }ecco una versione che utilizza un valore di ritorno (83 byte):

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

E sotto è una funzione che legge infinitamente molti valori dal flusso di input e spinge forme plurali nel flusso di output ( 87 83 byte):

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

È una funzione anonima, poiché è più breve della creazione di una funzione denominata.


Come si visualizza il risultato della prima funzione (quella che inizia con f&s)? Semplicemente f("word")non sembra mostrare nulla
Kritixi Lithos

@KritixiLithos Il parametro è un riferimento, quindi l'argomento deve essere una variabile.
Fergusq,

5

PHP, 103 100 byte

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

Provalo online!

La preg_replacefunzione comprende una serie di modelli e sostituzioni.

  • Salvato 2 byte grazie a Titus.
  • Salvato 1 byte grazie a Dewi Morgan.

2
Penso che puoi salvare un byte con -Re $argn. E usando un'asserzione con ydue risparmi: (?<![aeiou])y$consente iein sostituzione: no \1, senza virgolette.
Tito

1
Un altro byte da([^aeiou]o|sh?|x|z|ch)$
Dewi Morgan

@Titus In realtà sembra che ci sia una penalità di 1 byte per l'utilizzo -R(ma non -r) in modo da non modificare il conteggio dei byte, sfortunatamente. Ma il suggerimento lookbehind funziona benissimo. Grazie.
Kodos Johnson,

4

Python 3, 271 239 199 byte

Grazie a @ovs per averlo ridotto di 72 byte!

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"

Provalo online!


1
Puoi rimuovere alcuni spazi bianchi non necessari e combinare il primo e l'ultimo elif. Gli elenchi di singoli caratteri possono essere sostituiti da stringhe. Il passaggio a Python consente di risparmiare altri 3 byte. tio
ovs

@ovs Fatto, grazie! elifTuttavia non ho combinato la s, perché significa che potatodiventa potaties.
numbermaniac

1
Ho guardato nella riga sbagliata;). Puoi combinare if con l'ultimo elif. Per salvare qualche altro byte, sostituisci l'ultima riga con print(s+"s")e rimuovi il caso else e tutti gli altri che stai aggiungendo alla parola. Tio
ovs

1
Quando sostituisci la tua logica if / elif con and/*e or/+e fai una funzione lambda senza nome puoi ottenerla sotto 200 byte (ho scambiato un po 'i casi)
ovs

@ovs Ooh, print(s+"s")è intelligente. Tutto è cambiato; hai praticamente riscritto il tutto lol. Grazie! (Non sapevo nemmeno che potessi fare True and "string"così)
numbermaniac

2

sed, 70 79 byte

69 78 + 1 per -E(BSD) / -r(GNU) flag

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

Porta diretta della risposta della retina .


2

Pip , 63 61 byte

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

Così vicino a catturare Retina! Ma probabilmente non accadrà. :(

Provalo online!

Spiegazione

Strategia di base: R eplace esegue una serie di sostituzioni una dopo l'altra quando vengono fornite liste di modelli e sostituzioni. Vogliamo effettuare le seguenti sostituzioni:

  • (sh?|x|z|ch)$ -> aggiungi un e
  • [^aeiou]y-> cambia yini e aggiungi une
  • fe? -> cambia in v e aggiungi une
  • [^aeiou]o -> aggiungi un e

Quindi vogliamo puntare su un s prescindere.

Trucchi:

  • L' Coperatore, dato un regex, lo avvolge in un gruppo di cattura;C`xyz`è un byte più corta `(xyz)`.
  • È possibile creare un elenco di regex o sostituzioni che terminano tutte con lo stesso carattere concatenando il personaggio all'elenco anziché includendolo in tutti gli elementi. La concatenazione di uno scalare (stringa) a un modello (regex / sostituzione) si converte in un modello.
  • Invece di concatenare il s(e dover fare i conti con l'ordinamento di precedenza di Re .), possiamo semplicemente Opronunciare la parte principale della parola e quindi stampare sseparatamente.

Codice spaziato e commentato:

                  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

2

C #, 73 163 byte:

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

Sì, un'altra lingua integrata (anche se è necessario aggiungere un riferimento a System.Data.Entity.Design.dll)

Usare:

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

Produzione:

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios

Benvenuti nel sito. Come eseguo questo codice?
Wheat Wizard

@WheatWizard aggiornato. Avrei dovuto includere più dettagli (usando istruzioni ecc.) Nel conteggio dei byte?
RoadieRich

Interessante curiosità, il contrario di questo (Singularize) fallisce alcuni semplici casi di test. Ad esempio, è convinto che il singolare dei "corsi" sia "corsi".
Morgan Thrapp,

Penso che gli spazi dei nomi debbano essere inclusi nel conteggio dei byte di questo, soprattutto dato che non è uno di quelli "normali". Ma penso che anche tu debba almeno avvolgerlo in un lambda, passando l'argomento al metodo. Come è questo è solo un gruppo di metodi
pinkfloydx33

@ pinkfloydx33 meglio adesso?
RoadieRich

2

Python 199 187 176 byte

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'

2

Corridore di binari, 18 byte

$><<gets.pluralize

Esempio:

$ echo knife | rails r filename.rb
knives

Questo è un linguaggio esoterico.
Ven

2

Python, 296 byte

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')

0

Porto diretto di Retina:

Rubino , 111 byte

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

Provalo online!

Richiamare tramite ruby -lpee fornire un file come input.txtper il primo argomento della CLI.


Probabilmente può essere più "golfato". Btw .: È possibile aggiungere file a TIO?
stephanmg

0

C, 321 byte

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

test:

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

i risultati:

[car] [cars]
[bus] [buses]
[potato] [potatoes]
[knife] [knives]
[penny] [pennies]
[exception] [exceptions]
[wolf] [wolves]
[eye] [eyes]
[decoy] [decoys]
[radio] [radios]
[radio] [radios]

Dovrebbe essere wolvesnon wolfves.
mbomb007,

@ceilingcat per quanto riguarda "static C r [256], / * Z =" aeiou ", i = 0, w, n;" al posto di "statico C r [256]; C / * Z =" aeiou ", i = 0, w, n;"?
RosLuP


-1

Java 7, 408 byte

golfed:

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

Fondamentalmente testare qual è la fine della stringa e aggiungere / sostituire lettere a seconda del caso. Il valore booleano e String all'inizio servono solo per rimuovere la ripetizione nei casi di test e ridurre il codice.

Versione leggibile:

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

6
Non puoi utilizzare uno snippet.
Okx,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.