Преобразование единственного числа во множественное число

27

Существуют две формы существительных, единственного и множественного числа. Преобразование между этими двумя довольно легко.

  1. Обычно вы заканчиваете это s. ех. car=> cars.

  2. Если она заканчивается s, x, z, chили sh, в конце его es. ех. bus=> buses.

  3. Если она заканчивается yс согласным непосредственно перед ней, изменить yк ies. ех. penny=> pennies.

  4. Если оно заканчивается на fили fe, измените его на ves. ех. knife=> knives.

  5. Если oперед ним стоит согласный, измените его на oes. ех. potato=> potatoes.


задача

Вам дадут имя в единственном числе. Вы должны преобразовать данное существительное во множественное число и вывести его.


правила

  • Вам не дадут неправильные существительные, как mouseи moose.

  • Вам не будут предоставлены исключения, такие как safe( safes; нарушая № 4), piano( pianos; нарушая № 5) и o( oes, нарушая № 5).

  • Вам не дадут слова, которые имеют две или более возможные формы множественного числа, такие как mosquito( mosquitosили mosquitoes) и roof( roofsили rooves).

  • Вам не дадут неисчислимых существительных.

  • y не считается гласным


Примеры

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
Мэтью Ро
источник
Отредактированный вопрос для наглядности. Не стесняйтесь откат.
JungHwan Мин
11
Ааа, английский - огромная куча произвольных правил и особых случаев :)
Esolanging Fruit
38
@ Challenger5 Да, но вы можете понять это, если тщательно продумать мысли. ;)
Юнг Хван Мин
@ MatthewRoh Я отредактировал согласную в переднем правиле, чтобы сделать ее более понятной. Также добавлено несколько тестовых примеров для одного и того же. Если я неправильно понял, отредактируйте его, чтобы уточнить.
ghosts_in_the_code
2
@ Challenger5 Если вы сравниваете английский с нидерландским языком, то здесь вообще нет никаких правил. У нидерландского языка есть правила и особые случаи, а также особые случаи, противоречащие этим особым случаям, а в некоторых случаях даже особые случаи, которые противоречат тем особым случаям, которые противоречат этим особым случаям. ;)
Кевин Круйссен

Ответы:

46

Mathematica, 9 байт

Pluralize

Да, для этого есть встроенная функция!

Образец вывода

Pluralize["car"]

cars

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

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

Юнг Хван Мин
источник
6
Waaaaaat! Есть ли что-то, что Mathematica не имеет встроенного для?
KeyWeeUsr
2
D: Встроенные тоже напали на этот вызов
Мэтью Ро
1
@KeyWeeUsr codegolf.stackexchange.com/a/71680/56033
Азор Ахай
18

Retina , 57 53 56 55 58 57 байт

Спасибо MartinEnder за некоторые предложения по игре в гольф

Спасибо BusinessCat за игру в гольф 1 байт

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

Попробуйте онлайн!

Объяснение (устарело)

([^aeiou])y$
$1ie

Изменения {consonant}yв{consonant}ie

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

Присоединяет e, когда слово заканчивается {consonant}o, f, x, z, s, shили ch.

fe$
ve

Изменяет окончание feнаve

$
s

Наконец добавьте sк слову.

Правки

  • Добавлены байты, потому что я забыл второе правило
  • Добавлены байты для обновления eyeв качестве примера
Kritixi Lithos
источник
1
Извините, если это глупый вопрос, я не использовал Retina. Почему круглые скобки нужны в первой строке?
user2390246
Неважно, я думаю, что я ответил на свой вопрос. Это из-за обратной ссылки в следующей строке.
user2390246
Да, это потому, что мы хотим запечатлеть персонажа перед yиспользованием$1
Kritixi Lithos
Я думаю, что получил его в 57 байтов: попробуйте онлайн
Business Cat
16

JavaScript (ES6),  109  97 байт

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

Попробуйте онлайн!

Arnauld
источник
Почему у вас есть ()перед fe?
Кодос Джонсон
1
@KodosJohnson Все replace()итерации включают ссылку на первую подходящую группу (с $1). Вот почему мне нужна пустая подходящая группа здесь.
Арно
Ты пробовал (?<![aeiou])y?
Титус
@Titus К сожалению, JS не реализует утверждения за кадром.
Арно
11

Пакет, 325 байт

@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
Нил
источник
А @echo offв начале, а не @везде? Кроме того, @set/ps=кажется немного ржавым от телефона. Разве sпеременная не примет значения среза в любом случае?
KeyWeeUsr
@KeyWeeUsr @echo offуже 9 байтов без новой строки, так что это меня ничего не спасает. Кроме того, @set/ps=необходимо ввести значение в первую очередь.
Нил
7

Haskell, 216 207 205 байт

Спасибо @Lynn, @ user1472751 и @Laikoni за помощь!

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"

Удобочитаемый

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"

объяснение

import Data.Listдля функции isSuffixOf. endsWithOneOf( в версии для гольфа) возвращает, является ли один из элементов списка окончанием строки. consonants(c)это просто список всех согласных.

Наконец, pluralize(p)проверяет окончания и возвращает правильное множественное число.

Пример:

p "potato" == "potatoes"
Eisfunke
источник
1
Отличное решение! Это 216 символов , но его длина составляет несколько байтов, что делает ваше решение 226 байтов. (Задачи кода гольфа явно оцениваются в байтах, потому что подсчет символов позволяет иногда обманывать.) Однако вы можете просто переименовать его !! Также words"s x z ch sh"экономит 5 байт. Извлекает паренов вокруг (map(:"o")c))и (map(:"y")c))сохраняет еще 4.
Линн
Спасибо за помощь, @Lynn! Я реализовал ваши предложения.
Eisfunke
2
Вы можете сохранить один байт с помощью, c=['b'..'z']\\"eiou"поскольку 'a'всегда удаляется.
user1472751
1
0<1на один байт короче True. Кроме того, переводы строки имеют то же число байтов, что и ;делают гольф-код более читабельным.
Лайкони
5

Perl, 66 + 2 ( -plфлаг) = 68 байт

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

С помощью:

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

Попробуйте это на Ideone.

Денис Ибаев
источник
5

Röda , 80 байт

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

Функция изменяет свой аргумент. Использование: main word { f word; print word }Вот версия, которая использует возвращаемое значение (83 байта):

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

А ниже приведена функция, которая считывает бесконечно много значений из входного потока и помещает множественные формы в выходной поток ( 87 83 байта):

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

Это анонимная функция, так как она короче, чем создание именованной функции.

fergusq
источник
Как вы можете отобразить результат первой функции (начиная с f&s)? f("word")Кажется, просто ничего не отображается
Kritixi Lithos
@KritixiLithos Параметр является ссылкой, поэтому аргумент должен быть переменной.
fergusq
5

PHP, 103 100 байт

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

Попробуйте онлайн!

preg_replaceФункция принимает массив шаблонов и замены.

  • Сохранено 2 байта благодаря Титу.
  • Сохранено 1 байт благодаря Dewi Morgan.
Кодос Джонсон
источник
2
Я думаю, что вы можете сохранить один байт с помощью -Rи $argn. И использование утверждения с yсохранением два: (?<![aeiou])y$позволяет в ieкачестве замены: нет \1, без кавычек.
Титус
1
Еще один байт от([^aeiou]o|sh?|x|z|ch)$
Деви Морган
@Titus На самом деле похоже, что за использование -R(но не -r) есть 1 байтный штраф, что, к сожалению, не меняет счетчик байтов. Но предложение за кадром прекрасно работает. Спасибо.
Кодос Джонсон
4

Python 3, 271 239 199 байт

Спасибо @ovs за уменьшение его на 72 байта!

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"

Попробуйте онлайн!

numbermaniac
источник
1
Вы можете удалить некоторые ненужные пробелы и объединить первое и последнее elif. Односимвольные списки могут быть заменены строками. Переключение на python экономит дополнительные 3 байта. тио
овс
@ovs Готово, спасибо! Однако я не комбинировал elifs, потому что это означает, что potatoстановится potaties.
Numbermaniac
1
Я посмотрел не в ту строку;). Вы можете объединить if с последним elif. Чтобы сохранить еще несколько байтов, замените последнюю строку print(s+"s")и удалите регистр else, а также каждый s, который вы добавляете к слову. Тио
овс
1
Когда вы замените , если / Elif логику and/*и or/+и сделать безымянную функцию лямбды вы можете получить до 200 байт (я сменил случаи немного)
овс
@ovs Ох, это print(s+"s")умно. Все изменилось; Вы в значительной степени переписали все это, лол. Благодарность! (Я даже не знал, что вы могли бы сделать True and "string"это)
Numbermaniac
2

Пип , 63 61 байт

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

Так близко к ловле сетчатки! Но это, вероятно, не произойдет. :(

Попробуйте онлайн!

объяснение

Базовая стратегия: Replace выполняет несколько замен один за другим, когда даны списки шаблонов и замен. Мы хотим сделать следующие замены:

  • (sh?|x|z|ch)$ -> добавить e
  • [^aeiou]y-> изменить , yчтобы iи добавитьe
  • fe?-> изменить vи добавитьe
  • [^aeiou]o -> добавить e

Тогда мы хотим придерживаться sнезависимо.

Трюки:

  • CОператор, учитывая регулярное выражение, заворачивает в группе захвата; C`xyz`на один байт короче `(xyz)`.
  • Список регулярных выражений или замен, которые заканчиваются одним и тем же символом, может быть создан путем объединения символа в список вместо включения его во все элементы. Конкатенация скаляра (строки) с шаблоном (регулярное выражение / замена) приводит к шаблону.
  • Вместо того, чтобы объединять s(и иметь дело с порядком приоритета Rи .), мы можем просто Oвывести основную часть слова и затем распечатать sотдельно.

Размещенный и закомментированный код:

                  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
источник
2

C #, 73 163 байта:

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

Да, другой язык со встроенным (хотя вам нужно добавить ссылку на System.Data.Entity.Design.dll )

Использовать:

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

Выход:

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
RoadieRich
источник
Добро пожаловать на сайт. Как мне запустить этот код?
Wheat Wizard
@WheatWizard обновлен. Должен ли я включить более подробную информацию (с помощью операторов и т. Д.) В число байтов?
RoadieRich
Интересная мелочь, обратная сторона этого (Singularize) не проходит довольно много простых тестовых случаев. Например, он убежден, что единственное число «курсов» - это «курсы».
Морган Трепп
Я думаю, что пространства имен должны быть включены в число байтов этого, особенно учитывая, что это не одно из «нормальных». Но я думаю, что вам также нужно как минимум обернуть это в лямбду, передавая аргумент методу. Как это только метод группы
pinkfloydx33
@ pinkfloydx33 лучше сейчас?
RoadieRich
2

Питон 199 187 176 байт

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

Рельс бегун, 18 байт

$><<gets.pluralize

Пример:

$ echo knife | rails r filename.rb
knives
SztupY
источник
Теперь это эзотерический язык.
Ven
2

Python, 296 байт

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
источник
0

Прямой порт Retina:

Рубин , 111 байт

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

Попробуйте онлайн!

Вызвать через ruby -lpeи предоставить файл, как input.txtдля первого аргумента CLI.

stephanmg
источник
Вероятно, может быть более «гольф». Кстати: можно ли добавлять файлы в TIO?
stephanmg
0

C, 321 байт

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

тест:

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

полученные результаты:

[car] [cars]
[bus] [buses]
[potato] [potatoes]
[knife] [knives]
[penny] [pennies]
[exception] [exceptions]
[wolf] [wolves]
[eye] [eyes]
[decoy] [decoys]
[radio] [radios]
[radio] [radios]
RosLuP
источник
Она должна быть wolvesне wolfves.
mbomb007
@ceilingcat как насчет "static C r [256], / * Z =" aeiou ", i = 0, w, n;" вместо "статический C r [256]; C / * Z =" aeiou ", i = 0, w, n;"?
РосЛюП
1
260 байт
floorcat
-1

Java 7, 408 байт

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

В основном тестирование конца строки и добавление / замена букв в зависимости от того, какой это случай. Boolean и String в начале предназначены только для удаления повторений в тестовых примерах и уменьшения размера кода.

Читаемая версия:

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
Вы не можете использовать фрагмент.
Okx