Konwertuj liczbę pojedynczą na liczbę mnogą

27

Istnieją dwie formy rzeczowników: pojedyncza i mnoga. Konwersja między tymi dwoma jest dość łatwa.

  1. Zwykle kończysz to s. dawny. car=> cars.

  2. Jeśli kończy się s, x, z, chlub sh, zakończ go es. dawny. bus=> buses.

  3. Jeśli kończy ysię spółgłoską tuż przed nim, zmień ysię ies. dawny. penny=> pennies.

  4. Jeśli kończy się na flub fe, zmień na ves. dawny. knife=> knives.

  5. Jeśli kończy osię tuż przed nim spółgłoską, zmień ją na oes. dawny. potato=> potatoes.


Zadanie

Otrzymasz rzeczownik w liczbie pojedynczej. Musisz przekonwertować rzeczownik na liczbę mnogą i wyprowadzić go.


Zasady

  • Nie otrzymasz rzeczowników nieregularnych, takich jak mousei moose.

  • Nie otrzymasz wyjątków, takich jak safe( safes; naruszenie # 4), piano( pianos; naruszenie # 5) i o( oes, naruszenie # 5).

  • Nie otrzymasz słów, które mają dwie lub więcej możliwych form liczby mnogiej, takich jak mosquito( mosquitoslub mosquitoes) i roof( roofslub rooves).

  • Nie otrzymasz rzeczowników niepoliczalnych.

  • y nie liczy się jako samogłoska.


Przykłady

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
Matthew Roh
źródło
Edytowane pytanie dla jasności. Zapraszam do wycofania.
JungHwan Min
11
Ahh, angielski - ogromny stos arbitralnych zasad i specjalnych przypadków :)
Esolanging Fruit
38
@ Challenger5 Tak, ale możesz to zrozumieć poprzez trudne, gruntowne przemyślenia. ;)
JungHwan Min
@MatthewRoh Zredagowałem regułę spółgłoski z przodu, aby była bardziej przejrzysta. Dodano również kilka przypadków testowych dla tego samego. Jeśli źle zrozumiałem, edytuj go, aby wyjaśnić.
ghosts_in_the_code
2
@ Challenger5 Jeśli porównasz angielski do holenderskiego, prawie nie ma żadnych reguł. W holenderskim obowiązują zasady i specjalne przypadki, a także specjalne przypadki sprzeczne z tymi szczególnymi przypadkami, aw niektórych przypadkach nawet specjalne przypadki, które są sprzeczne z tymi szczególnymi przypadkami, które są sprzeczne z tymi szczególnymi przypadkami. ;)
Kevin Cruijssen

Odpowiedzi:

46

Mathematica, 9 bajtów

Pluralize

Tak, jest do tego wbudowany!

Próbka wyjściowa

Pluralize["car"]

cars

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

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

JungHwan Min
źródło
6
Waaaaaat! Czy jest coś, dla czego Mathematica nie ma wbudowanego?
KeyWeeUsr
2
D: Wbudowane również zaatakowały to wyzwanie
Matthew Roh
18

Retina , 57 53 56 55 58 57 bajtów

Dzięki MartinEnder za sugestie dotyczące gry w golfa

Dzięki BusinessCat za grę w golfa 1 bajt

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

Wypróbuj online!

Wyjaśnienie (nieaktualne)

([^aeiou])y$
$1ie

Zmiany {consonant}yna{consonant}ie

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

Dołącza edo tego, kiedy kończy się słowo z {consonant}o, f, x, z, s, shlub ch.

fe$
ve

Zmienia zakończenie fenave

$
s

Na koniec dodaj sdo słowa.

Edycje

  • Dodano bajty, ponieważ zapomniałem drugiej reguły
  • Dodano bajty do aktualizacji eyejako przykład
Kritixi Lithos
źródło
1
Przepraszam, jeśli to głupie pytanie, nie użyłem Retiny. Dlaczego nawiasy okrągłe są potrzebne w pierwszej linii?
user2390246
Nieważne, myślę, że odpowiedziałem na własne pytanie. Jest to spowodowane odwołaniem wstecznym w poniższym wierszu.
user2390246
Tak, ponieważ chcemy uchwycić postać przed yużyciem$1
Kritixi Lithos
Myślę, że mam go w 57 bajtach: Wypróbuj online
Business Cat
16

JavaScript (ES6),  109  97 bajtów

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

Wypróbuj online!

Arnauld
źródło
Dlaczego masz ()przed sobą fe?
Kodos Johnson
1
@KodosJohnson Wszystkie replace()iteracje zawierają odniesienie do pierwszej pasującej grupy (z $1). Dlatego potrzebuję tutaj pustej pasującej grupy.
Arnauld,
Próbowałeś (?<![aeiou])y?
Tytus
@Titus Niestety JS nie implementuje twierdzeń lookbehind.
Arnauld
11

Partia, 325 bajtów

@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
źródło
A może @echo offna początku, a nie @wszędzie? Poza tym @set/ps=wydaje się trochę zardzewiały z telefonu. Czy szmienna i tak nie zaakceptuje wartości krojenia?
KeyWeeUsr
@KeyWeeUsr @echo offma już 9 bajtów bez nowej linii, więc nic mnie nie oszczędza. Ponadto @set/ps=konieczne jest, aby wprowadzić wartość w pierwszej kolejności.
Neil
7

Haskell, 216 207 205 bajtów

Dzięki @Lynn, @ user1472751 i @Laikoni za pomoc!

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"

Czytelny

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"

Wyjaśnienie

import Data.Listdla funkcji isSuffixOf. endsWithOneOf( w wersji golfowej) zwraca informację, czy jeden z elementów listy jest końcem ciągu. consonants(c)to tylko lista wszystkich spółgłosek.

Na koniec pluralize(p)sprawdza zakończenia i zwraca odpowiednią liczbę mnogą.

Przykład:

p "potato" == "potatoes"
Eisfunke
źródło
1
Fajne rozwiązanie! Ma 216 znaków , ale ma wiele bajtów, co czyni rozwiązanie 226 bajtami. (Wyzwania związane z golfem kodowym są jednoznacznie punktowane w bajtach, ponieważ zliczanie znaków pozwala czasem oszukiwać.) Możesz jednak zmienić jego nazwę !! Ponadto words"s x z ch sh"oszczędza 5 bajtów. Usuwając parens (map(:"o")c))i (map(:"y")c))oszczędzasz 4 kolejne.
Lynn,
Dzięki za pomoc, @Lynn! Wdrożyłem twoje sugestie.
Eisfunke
2
Możesz zapisać jeden bajt, c=['b'..'z']\\"eiou"ponieważ 'a'jest zawsze usuwany.
user1472751
1
0<1jest o jeden bajt krótszy niż True. Również nowe wiersze mają tę samą liczbę bajtów, ;ale sprawiają, że kod w golfa jest nieco lepiej czytelny.
Laikoni
5

Perl, 66 + 2 ( -plflaga) = 68 bajtów

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

Za pomocą:

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

Wypróbuj na Ideone.

Denis Ibaev
źródło
5

Röda , 80 bajtów

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

Funkcja modyfikuje swój argument. Użycie: main word { f word; print word }Oto wersja, która używa wartości zwracanej (83 bajty):

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

Poniżej znajduje się funkcja, która odczytuje nieskończenie wiele wartości ze strumienia wejściowego i wypycha liczbę mnogą do strumienia wyjściowego ( 87 83 bajtów):

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

Jest to funkcja anonimowa, ponieważ jest krótsza niż tworzenie funkcji nazwanej.

fergusq
źródło
Jak wyświetlić wynik pierwszej funkcji (tej rozpoczynającej się od f&s)? Po prostu f("word")nic nie wyświetla
Kritixi Lithos
@KritixiLithos Parametr jest odwołaniem, więc argument musi być zmienną.
fergusq
5

PHP, 103 100 bajtów

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

Wypróbuj online!

preg_replaceFunkcja wykonuje się w szeregu wzorów i wymiany.

  • Zaoszczędzono 2 bajty dzięki Tytusowi.
  • Zaoszczędzono 1 bajt dzięki Dewi Morganowi.
Kodos Johnson
źródło
2
Myślę, że możesz zapisać jeden bajt za pomocą -Ri $argn. A użycie twierdzenia z yzapisem dwa: (?<![aeiou])y$pozwala iena zastąpienie: nie \1, bez cudzysłowów.
Tytus
1
Kolejny bajt od([^aeiou]o|sh?|x|z|ch)$
Dewi Morgan
@Titus W rzeczywistości wygląda na to, że istnieje 1 bajtowa kara za użycie -R(ale nie -r), więc nie zmienia to liczby bajtów, niestety. Ale sugestia wyglądu działa świetnie. Dzięki.
Kodos Johnson
4

Python 3, 271 239 199 bajtów

Dzięki @ovs za zmniejszenie go o 72 bajty!

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"

Wypróbuj online!

NumberManiac
źródło
1
Możesz usunąć niepotrzebne białe znaki i połączyć pierwszą i ostatnią elif. Listy pojedynczych znaków można zastąpić ciągami. Przejście na Python oszczędza dodatkowe 3 bajty. tio
ovs
@ovs Gotowe, dziękuję! Nie połączyłem elifjednak s, ponieważ to oznacza, że potatostaje się potaties.
numbermaniac
1
Patrzyłem w niewłaściwą linię;). Możesz połączyć if z ostatnim elifem. Aby zaoszczędzić trochę więcej bajtów, zamień ostatni wiersz na print(s+"s")i usuń także literę else oraz każdą dołączaną do słowa. Tio
ovs
1
Kiedy zamienisz logikę if / elif na and/*i or/+wykonasz nienazwaną funkcję lambda, możesz uzyskać ją poniżej 200 bajtów (nieco zamieniłem skrzynki)
dniu
@ovs Ooh, print(s+"s")to sprytne. Wszystko zmienione; napisałeś prawie wszystko, lol. Dzięki! (Nawet nie wiedziałem, że możesz to zrobić True and "string")
numermaniak
2

sed, 70 79 bajtów

69 78 + 1 dla flagi -E(BSD) / -r(GNU)

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

Bezpośredni port odpowiedzi siatkówki .

Kevin
źródło
2

Pip , 63 61 bajtów

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

Tak blisko złapania siatkówki! Ale prawdopodobnie tak się nie stanie. :(

Wypróbuj online!

Wyjaśnienie

Podstawowa strategia: Replace wykonuje kilka zamian jedna po drugiej, gdy podane są listy wzorców i zamienników. Chcemy dokonać następujących zamienników:

  • (sh?|x|z|ch)$ -> dodaj e
  • [^aeiou]y-> zmienić ysię ii dodaje
  • fe?-> zmień vi dodaje
  • [^aeiou]o -> dodaj e

Następnie chcemy zająć się s niezależnie.

Wydziwianie:

  • COperatora, ponieważ wyrażenie regularne, zawija się w grupie chwytu; C`xyz`jest o jeden bajt krótszy niż`(xyz)` .
  • Listę wyrażeń regularnych lub zamienników, które kończą się tym samym znakiem, można utworzyć, łącząc znak z listą zamiast umieszczać go we wszystkich elementach. Łączenie skalarnego (łańcucha) ze Wzorem (wyrażenia regularne / zamiana) wymusza Wzorzec.
  • Zamiast łączyć s(i zajmować się kolejnością pierwszeństwa Ri .), możemy po prostu Owypowiedzieć główną część słowa, a następnie wydrukować sosobno.

Kod z odstępami i komentarzami:

                  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
źródło
2

C #, 73 163 bajty:

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

Tak, inny język z wbudowanym (choć musisz dodać odniesienie System.Data.Entity.Design.dll)

Używać:

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

Wydajność:

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
RoadieRich
źródło
Witamy na stronie. Jak uruchomić ten kod?
Kreator pszenicy,
@WheatWizard zaktualizowane. Czy powinienem zawrzeć więcej szczegółów (używając instrukcji itp.) W liczbie bajtów?
RoadieRich
Ciekawa ciekawostka, na odwrót tego (Singularize) zawodzi kilka prostych przypadków testowych. Na przykład jest przekonany, że liczba pojedyncza „kursów” to „cours”.
Morgan Thrapp
Myślę, że przestrzenie nazw muszą być uwzględnione w tym bajcie, szczególnie biorąc pod uwagę, że nie jest to jeden z „normalnych”. Ale myślę, że musisz także zawinąć to w lambda, przekazując argument do metody. Jest to tylko grupa metod
pinkfloydx33
@ pinkfloydx33 lepiej teraz?
RoadieRich
2

Python 199 187 176 bajtów

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
źródło
2

Runner Rails, 18 bajtów

$><<gets.pluralize

Przykład:

$ echo knife | rails r filename.rb
knives
Sztuczki
źródło
To jest ezoteryczny język.
Ven
2

Python, 296 bajtów

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
źródło
0

Bezpośredni port Retina:

Rubin , 111 bajtów

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

Wypróbuj online!

Wywołaj przez ruby -lpei podaj plik jak input.txtdla pierwszego argumentu CLI.

stephanmg
źródło
Prawdopodobnie może być bardziej „golfowy”. Btw .: Czy można dodawać pliki do TIO?
stephanmg
0

C, 321 bajtów

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

wyniki:

[car] [cars]
[bus] [buses]
[potato] [potatoes]
[knife] [knives]
[penny] [pennies]
[exception] [exceptions]
[wolf] [wolves]
[eye] [eyes]
[decoy] [decoys]
[radio] [radios]
[radio] [radios]
RosLuP
źródło
Powinno być wolvesnie wolfves.
mbomb007
@ceilingcat co z "static C r [256], / * Z =" aeiou ", i = 0, w, n;" zamiast „static C r [256]; C / * Z =„ aeiou ”, i = 0, w, n;"?
RosLuP,
1
260 bajtów
pułap pułapu
-1

Java 7, 408 bajtów

Gra w golfa:

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

Zasadniczo testowanie końca łańcucha i dodawanie / zastępowanie liter w zależności od przypadku. Wartości boolean i String na początku służą do usuwania powtórzeń w przypadkach testowych i zmniejszania kodu.

Wersja do odczytu:

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";
}
Nacięcie
źródło
6
Nie możesz użyć fragmentu.
Okx,