Удалите неоднозначное множественное число (я)!


21

Программирование очень жесткое. Вы не можете указать программе «выводить количество бананов», вы должны сообщить об этом print(bananas).

Но когда вы делаете это, вы сталкиваетесь с проблемой: вы не знаете, сколько у вас бананов заранее, поэтому вы не знаете, стоит ли использовать множественное число.

Иногда программисты идут ленивым путем. Вместо проверки они просто печатают there are X banana(s).

Но это ужасно, поэтому нам нужна программа, чтобы это исправить.

Метод (ы)

Чтобы удалить неоднозначное множественное число в строке, выполните следующие действия:

  1. Разбейте строку на пробелы в список слов.

  2. Для каждого слова, которое заканчивается на (s), сделайте следующее:

    • Если предшествующий слово a, an, 1или one, удалить (s)в конце слова.
    • В противном случае, если слово является первым словом в строке или предыдущее слово не a, an, 1или one, заменить (s)в конце слова с s.
  3. Соедините список слов обратно в строку, сохранив исходный пробел.

Примеры)

Давайте возьмем строку there's a banana(s) and three apple(s).

Сначала мы разбиваем строку на список слов: ["there's", "a", "banana(s)", "and", "three", "apple(s)"]

Для второго шага мы берем два слова, заканчивающиеся на (s): banana(s)и apple(s).

Слово раньше banana(s)есть a, поэтому мы удаляем (s), делая это banana. Слово , прежде чем apple(s)это three, так что мы изменить , (s)чтобы s, таким образом , она становится apples.

Теперь у нас есть ["there's", "a", "banana", "and", "three", "apples"]. Присоединяясь к списку вместе, мы получаем there's a banana and three apples. Это наш конечный результат.

Испытания)

Создайте программу или функцию, которая принимает неоднозначную строку в любом приемлемом формате и возвращает однозначную версию этой строки.

Вы можете предположить, что строка не содержит символов новой строки, табуляции или возврата каретки.

Я забыл указать, нужно ли разбивать группы пробелов или пробелов (то есть, следует ли использовать okay thenдва пробела ["okay", "then"]или ["okay", "", "then"]) при публикации задания , так что вы можете принять любую форму расщепления.

Тестовый набор (ы)

Input                                         -> Output
there are two banana(s) and one leprechaun(s) -> there are two bananas and one leprechaun
there's a banana(s) and three apple(s)        -> there's a banana and three apples
apple(s)                                      -> apples
one apple(s)                                  -> one apple
1 banana(s)                                   -> 1 banana
banana                                        -> banana
preserve    original      whitespace(s)       -> preserve    original      whitespaces
11 banana(s)                                  -> 11 bananas
an apple(s)                                   -> an apple
this is a te(s)t                              -> this is a te(s)t
I am a (s)tranger(s)                          -> I am a (s)tranger

счет

Поскольку это , выигрывает представление с наименьшим количеством байтов!


Этот вопрос был в песочнице .
LyricLy

Должен ли apple(s)тестовый набор дать результат apples? Задача Otherwise, if the word is the first word in the string . . . replace the (s) at the end of the word with s.состоит в том, чтобы отметить, что этот случай уступил applesв песочнице для первых трех ревизий, но изменился на четвертой.
fireflame241

@ fireflame241 При написании второго проекта правил я собирался сделать так, чтобы начало строки не изменилось. Я изменил это правило позже, но не тестовый пример. Хороший улов.
LyricLy

Тестовый пример: There's a single banana(s)-> There's a single bananas.
Джонатан Аллан

1
@JonathanAllan Вы не можете. Я добавлю несколько тестовых случаев.
LyricLy

Ответы:


6

Mathematica, 151 148 байт

StringReplace[j=" ";k=Except@j;j<>j<>#<>j,j~~a:k...~~s:j..~~w:k..~~"(s)"~~j:>{j,a,s,w,If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""]}<>j]~StringTake~{3,-2}&

объяснение

j=" ";k=Except@j

Установите jпробельные символы. Установите kдля шаблона «not j» (= непробельный символ).

j<>j<>#<>j

Добавьте два пробела и добавьте один пробел к входным данным.

j~~a:k...~~s:j..~~w:k..~~"(s)"~~j

Для подстроки, соответствующей шаблону:

  1. Один пробел, а затем
  2. подстрока длиной ноль или более, состоящая только из непробельных символов (квантификатор) (вызовите это a), за которым следует
  3. подстрока длиной в одну или более длинную, состоящую только из символов пробела (вызовите это s), за которыми следует
  4. подстрока длиной одна или более, состоящая только из непробельных символов (слов) (вызовите это w), за которыми следует
  5. строка "(s)", сопровождаемая
  6. пробел (ы)
Если [FreeQ [а, "а" | "ЭН" | "1" | "один"], "s", ""]

Если aэто не одно из единственного слова, оцените "s"иначе "".

StringReplace[..., ... :>{j,a,s,w,If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""]}<>j]

Заменить шаблон согласования с j, a, s, w, If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""], и jсоединены друг с другом.

... ~StringTake~{3,-2}

Возьмите из позиции 3 в позицию -2 (индексирован 1; отрицательные индексы отсчитываются с конца). Это потому, что мы добавили три пробела в начале.


3
Почему бы не использовать встроенную функцию для удаления множественного числа-S?
Томас Веллер

5

Python 3 , 94 байта

lambda s,r=re.sub:r(r"\(s\)( |$)","s",r(r"\b(an?|1|one)(\s+)(.+)\(s\)",r"\1\2\3",s))
import re

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

-4 байта, благодаря I Cri Everytim (я думаю, что это приемлемо)


@JonathanAllan Исправлено, спасибо.
HyperNeutrino

1
__import__не может быть короче ... Да, это на 4 байта короче обычного import re.
полностью человек

@icrieverytim да ты прав (всего 3 байта) спасибо
HyperNeutrino


@icrieverytim ._. о, классно. Благодарность!
HyperNeutrino


4

Mathematica, 313 байтов

(Table[If[StringLength@z[[i]]>3&&StringTake[z[[i]],-3]=="(s)",z[[i]]=StringDrop[z[[i]],-3];t=1;While[z[[i-t]]=="",t++];If[FreeQ[{"a","an","1","one"},z[[i-t]]],z[[i]]=z[[i]]<>"s"]],{i,2,Length[z=StringSplit[#," "]]}];If[StringTake[z[[1]],-3]=="(s)",z[[1]]=StringDrop[z[[1]],-3];z[[1]]=z[[1]]<>"s"];StringRiffle@z)&

3

Perl 5, 43 + 1 (-p) = 44 байта

s/\b((one|1|an?) +)?\S+\K\(s\)\B/"s"x!$1/ge

Подберите каждый (s)конец слова, замените его на !$1(1 или 0).


2

Pyth - 53 байта

Следует алгоритму в значительной степени, как есть.

K+kczdjdt.e?q"(s)"gb_2+<b_3*\s!}@Ktk[\a"an""one"\1)bK

Попробуйте это онлайн здесь .


1
Сбой there are two banana(s) and one leprechaun(s)(два пробела после one). Оригинальный пробел сохраняется, но leprechaun(s)игнорируетone перед ним.
LyricLy

1
@LyricLy вы не указали это явно в OP. С двумя пробелами (используя (1) вашего раздела «method (s)» раздела «разбить строку на пробелы в список слов»), на самом деле пустое слово между oneиleprechaun(s)
Jonathan Allan

2

Желе ,  52 51  49 байт

У желе нет одного атома регулярного выражения

Ṫ
Ñ;”s
Ṫḣ-3
UṪw“)s(”⁼1
“µḣ⁴µuʠg*»ḲċḢ‘×Ç‘
⁶;ḲÇĿ2ƤK

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

Попробуйте онлайн! или посмотрите набор тестов .

Как?

Ṫ - Link 1, tail: two words (list of lists)
Ṫ - tail

Ñ;”s - Link 2, tail and replace last three chars with an 's': two words (list of lists)
Ñ    - call the next link (3) as a monad
  ”s - literal 's'
 ;   - concatenate

Ṫḣ-3 - Link 3, tail and remove the last three chars: two words (list of lists)
Ṫ    - tail
  -3 - literal minus three
 ḣ   - head from index (1-indexed and modular)

UṪw“)s(”⁼1 - Link 4, tail ends with "(s)"?: two words (list of lists)
U          - upend (reverse each word)
 Ṫ         - tail
   “)s(”   - literal [')', 's', '('] - that is "(s)" reversed
  w        - index of first sublist equal to that or 0 if not found
         1 - literal one
        ⁼  - equal?

“µḣ⁴µuʠg*»ḲċḢ‘×Ç‘ - Link 5, categorise: two words (list of lists)
“µḣ⁴µuʠg*»        - compression of string "a 1" + word " an" + word " one"
          Ḳ       - split on spaces = ["a", "1", "an", "one"]
            Ḣ     - head (the first word)
           ċ      - count occurrences (of head in the list - either 0 or 1)
             ‘    - increment
               Ç  - call the last link (4) as a monad - i.e. f(two words)
              ×   - multiply
                ‘ - increment - so we have: 1 for ["1", "blah"],
                  -             2 for ["blah", "blah(s)"] or 3 for ["1", "blah(s)"]

⁶;ḲÇĿ2ƤK - Main link: list of characters, the string
⁶        - literal space character
 ;       - concatenate (place a space at the beginning as we want to inspect pairs)
  Ḳ      - split on spaces (giving an empty list at the start)
     2Ƥ  - for all infixes of length two:
    Ŀ    -   call the link at the given index as a monad:
   Ç     -     call the last link (5) as a monad
       K - join the result with spaces
         - implicit print

Мне интересно, почему вы использовали в качестве отдельной ссылки. Это мешает удалить элемент из исходного списка?
HyperNeutrino

Нет, мне нужно узнать пару слов ... написать комментарий к коду, может быть, вы сможете увидеть гольф, как только увидите это.
Джонатан Аллан

Ах хорошо. Спасибо, я постараюсь найти гольф, как только появится комментарий (или раньше)!
HyperNeutrino

Таким образом, ссылки 1, 2 и 3 все заканчиваются, а ссылка 5 выбирает, какой из них вызывать, и использует Ŀдля этого, но я не вижу короткого пути к хвосту внутри ссылки 4, но это возможно. Там может быть даже способ получить хвост ссылки 4 там же!
Джонатан Аллан

@HyperNeutrino Я думаю, что Ŀвещь может называть первую ссылку, поэтому это ссылка сама по себе.
Эрик Outgolfer


1

Perl 5 , 56 + 1 ( -p) = 57 байт

s/\b(an?|1|one) +\S+\K\(s\)(?= |$)//g;s/\(s\)( |$)/s$1/g

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


1
Не в тестовых случаях, но я думаю, что это не удается a hel(s)lo.
Нил

Это работает правильно, как предусмотрено в тестовом примере. Это в нижней части тестовых случаев в моей ссылке TIO.
17

Ну, я просто должен быть a hel(s)loдобавлен в тестовые
Нил

0

JavaScript (ES6), 88 87 байт

a=>a.replace(/(\S+)( +)(\S+)\(s\)/g,(m,f,s,w)=>f+s+w+(/^(a|an|1|one)$/.exec(f)?'':'s'))

Объяснение в ближайшее время.


1
Вы можете заменить \sна `` в соответствии с "Вы можете предположить, что строка не содержит ни перевода строки, ни табуляции, ни возврата каретки."
SuperStormer

Сбой на "это te (s) t". Вы можете исправить это, добавив (\s|$)в конец регулярное выражение.
Birjolaxew

Также терпит неудачу на "яблоко (ах)". Исправлено в этом
TIO

Спасибо @Birjolaxew, буду редактировать изменения, когда смогу ...
XavCo7

0

JavaScript (ES6), 84 байта

s=>s.replace(/((^|\S+ +)\S+)\(s\)(?!\S)/g,(_,a)=>a+(/^(1|an?|one) /.test(a)?'':'s'))

Вот интересный способ переставить последнюю часть, которая, к сожалению, на 2 байта длиннее:

s=>s.replace(/((^|\S+ +)\S+)\(s\)(?!\S)/g,(_,a)=>a+'s'.slice(/^(1|an?|one) /.test(a)))

0

JavaScript (SpiderMonkey) , 82 байта

s=s.replace(/(\S+ +(\S+))\(s\)\B/g,(_,a)=>a+("s"[+/^(1|one|an?)\b/i.test(a)]||""))

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

78-байтовая версия (менее надежная)

s=s.replace(/(\S+ +(\S*))\(s\)/g,(_,a)=>a+("s"[+/^(1|one|an?)/i.test(a)]||""))

Это модифицированная версия ETHproductions '(у меня нет 50 представителей)

объяснение

  • /(\S+ +(\S+))\(s\)/g- фактический шаблон для поиска ( amount object(s))
  • (_,a)=>a- _это переменная ловить все, aявляется(\S+ +(\S+))
  • "s"[+/^(1|one|an?)/i.test(a)]||"" - вместо нарезки массива просто создайте фиктивный массив и получите индекс (+/.../.test возвращает число)
    • должен "s"[+/^(1|one|an?)/i.test(a)]вернуть undefined( trueили 1для теста) возврат""
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.