Usuń niejednoznaczne liczby mnogie!


21

Programowanie jest bardzo sztywne. Nie możesz powiedzieć programowi, aby „wyprowadzał liczbę bananów”, musisz to powiedzieć print(bananas).

Ale kiedy to robisz, pojawia się problem: nie wiesz, ile masz wcześniej bananów, więc nie wiesz, czy użyć liczby mnogiej.

Czasami programiści idą leniwie. Zamiast sprawdzać, po prostu drukują there are X banana(s).

Ale to brzydkie, więc potrzebujemy programu, aby to naprawić.

Metody)

Aby usunąć niejednoznaczne liczby mnogie z ciągu, wykonaj następujące kroki:

  1. Podziel ciąg znaków na spacje na listę słów.

  2. Dla każdego słowa, które kończy się na (s), wykonaj następujące czynności:

    • Jeśli poprzedzający słowo jest a, an, 1lub one, usunąć (s)na końcu wyrazu.
    • W przeciwnym razie, jeśli słowo jest pierwsze słowo w łańcuchu lub poprzedniego słowa nie ma a, an, 1lub one, wymienić (s)na końcu słowa z s.
  3. Połącz listę słów z powrotem w ciąg znaków, zachowując oryginalne białe znaki.

Przykład (y)

Weźmy sznurek there's a banana(s) and three apple(s).

Najpierw podzielimy ciąg na listę słów: ["there's", "a", "banana(s)", "and", "three", "apple(s)"]

W drugim kroku bierzemy dwa słowa kończące się na (s): banana(s)i apple(s).

Słowo przedtem banana(s)brzmi a, więc usuwamy go (s), czyniąc go banana. Słowo przed apple(s)to three, więc możemy zmienić (s), aby sw ten sposób staje się apples.

Teraz mamy ["there's", "a", "banana", "and", "three", "apples"]. Łączymy listę z powrotem, otrzymujemy there's a banana and three apples. To jest nasz wynik końcowy.

Wyzwania)

Utwórz program lub funkcję, która pobiera niejednoznaczny ciąg znaków w dowolnym rozsądnym formacie i zwraca niejednoznaczną wersję tego ciągu.

Możesz założyć, że ciąg nie zawiera znaków nowej linii, tabulatorów ani znaków powrotu karetki.

Zapomniałem określić, czy podzielić na grupy spacji czy spacji (tj. Czy okay thendwie spacje powinny być ["okay", "then"]lub ["okay", "", "then"]) podczas publikowania wyzwania, więc możesz założyć dowolną formę podziału.

Przypadki testowe)

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

Punktacja

Ponieważ jest to , wygrywa zgłoszenie z najmniejszą liczbą bajtów!


To pytanie zostało piaskownicy .
LyricLy 30.09.17

Czy zamiast tego apple(s)test powinien dać wynik apples? Wyzwanie stwierdza, Otherwise, if the word is the first word in the string . . . replace the (s) at the end of the word with s.że zauważam, że ten przypadek przyniósł applesw piaskownicy pierwsze trzy wersje, ale zmienił się przy czwartej.
fireflame241

@ fireflame241 Pisząc drugi szkic zasad, zamierzałem to zrobić, aby początek łańcucha pozostał niezmieniony. Później zmieniłem tę zasadę, ale nie przypadek testowy. Dobry chwyt
LyricLy

Sugestia przypadku testowego: There's a single banana(s)-> There's a single bananas.
Jonathan Allan

1
@JonathanAllan Nie możesz. Dodam kilka przypadków testowych.
LyricLy,

Odpowiedzi:


6

Mathematica, 151 148 bajtów

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

Wyjaśnienie

j=" ";k=Except@j

Ustaw jna znak (białe znaki). Ustaw kna wzorzec „nie j” (= znak inny niż biały znak).

j<>j<>#<>j

Dodaj dwa białe znaki i dodaj jeden biały znak do danych wejściowych.

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

W przypadku podciągów pasujących do wzoru:

  1. Jeden biały znak (i), a następnie
  2. podłańcuch o zerowej długości lub długości składający się wyłącznie ze znaków niebędących spacjami (kwantyfikator) (nazwij to a), a następnie
  3. podłańcuch o długości jeden lub dłuższy składający się tylko z białych znaków (nazwij to s), po których następuje
  4. podłańcuch o długości jeden lub dłuższy składający się wyłącznie ze znaków niebędących białymi znakami (słowem) (nazwij to w), po których następuje
  5. ciąg "(s)", a następnie
  6. białe znaki
Jeśli [FreeQ [a, "a" | "an" | "1" | "one"], "s", ""]

Jeśli anie jest jednym z pojedynczych słów, oceń "s", w przeciwnym razie "".

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

Wymień wzór pasujący z j, a, s, w, If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""], i jpołączone ze sobą.

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

Przejmij od pozycji 3 do pozycji -2 (indeksowane 1; ujemne wskaźniki liczą się od końca). Jest tak, ponieważ na początku dodaliśmy trzy spacje.


3
Dlaczego nie użyć wbudowanego narzędzia do usunięcia liczby mnogiej-S?
Thomas Weller

5

Python 3 , 94 bajty

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

Wypróbuj online!

-4 bajty dzięki i cri everytim (myślę, że jest to dopuszczalne)


@JonathanAllan Naprawiono, dziękuję.
HyperNeutrino

1
__import__nie może być krótszy ... Tak, jest o 4 bajty krótszy jak zwykle import re.
całkowicieludzki

@icrieverytim huh masz rację (tylko 3 bajty) dzięki
HyperNeutrino


@icrieverytim ._. och miło. dzięki!
HyperNeutrino


4

Mathematica, 313 bajtów

(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 bajty

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

Dopasuj każdy (s)na końcu słowa, zamień go na !$1(1 lub 0) esse.


2

Pyth - 53 bajty

Podąża za algorytmem właściwie takim, jakim jest.

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

Wypróbuj online tutaj .


1
Nie there are two banana(s) and one leprechaun(s)działa (dwa spacje po one). Oryginalna biała spacja zostaje zachowana, ale leprechaun(s)ignoruje oneją wcześniej.
LyricLy 30.09.17

1
@LyricLy nie podałeś tego wprost w PO. W przypadku dwóch spacji (używając (1) sekcji „metody” w sekcji „podziel ciąg znaków na spacje na listę słów”) w rzeczywistości jest puste słowo pomiędzy oneileprechaun(s)
Jonathan Allan

2

Galaretka ,  52 51  49 bajtów

Galaretka nie ma jednego atomu wyrażenia regularnego

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

Pełny program akceptujący ciąg (wykorzystujący formatowanie w języku Python, jeśli zawiera wiele wierszy lub zawierający cudzysłowy) i drukujący dane wyjściowe.

Wypróbuj online! lub zobacz zestaw testowy .

W jaki sposób?

Ṫ - 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

Jestem ciekawy, dlaczego użyłeś go jako osobnego linku. Czy to uniemożliwia usunięcie elementu z oryginalnej listy?
HyperNeutrino

Nie, muszę zdobyć ogon pary ... pisząc komentarz do kodu, może zobaczysz golfa, kiedy to zobaczysz.
Jonathan Allan

Ah, dobrze. Dzięki, postaram się dostrzec golfa, gdy pojawi się komentarz (lub wcześniej)!
HyperNeutrino

Tak więc linki 1, 2 i 3 są ogonem, a link 5 wybiera, do Ŀkogo zadzwonić, i używa do tego celu, ale nie widzę krótkiej drogi do ogonienia wewnątrz linku 4, ale może być. Może być nawet sposób na umieszczenie tam ogona łącza 4!
Jonathan Allan

@HyperNeutrino Myślę, że rzecz Ŀmoże nazwać pierwszy link, dlatego jest linkiem samo w sobie.
Erik the Outgolfer


1

Perl 5 , 56 + 1 ( -p) = 57 bajtów

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

Wypróbuj online!


1
Nie w przypadkach testowych, ale myślę, że to się nie udaje a hel(s)lo.
Neil,

Działa to poprawnie, jak podano w przypadku testowym. Jest blisko dolnej części przypadków testowych w moim łączu TIO.
Xcali,

Cóż, muszę tylko a hel(s)lododać do przypadków testowych, a potem może naprawisz swój kod ...
Neil

0

JavaScript (ES6), 88 87 bajtów

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

Wyjaśnienie już wkrótce.


1
możesz zastąpić \ssłowem „zgodnie z” Możesz założyć, że ciąg nie zawiera znaków nowej linii, tabulatorów ani znaków powrotu karetki. ”
SuperStormer,

Nie działa „to jest te (s) t”. Możesz to naprawić, dodając (\s|$)na końcu wyrażenia regularnego.
Birjolaxew

Również zawodzi w przypadku „jabłek”. Naprawiono w tym TIO
Birjolaxew

Dzięki @ Birjolaxew, będę edytować zmiany, kiedy będę mógł ...
XavCo7

0

JavaScript (ES6), 84 bajtów

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

Oto ciekawy sposób na zmianę kolejności ostatniej części, która jest niestety o 2 bajty dłuższa:

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

0

JavaScript (SpiderMonkey) , 82 bajty

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

Wypróbuj online!

Wersja 78 bajtów (mniej wytrzymała)

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

To jest zmodyfikowana wersja ETHproductions ”(nie mam 50 powtórzeń)

Wyjaśnienie

  • /(\S+ +(\S+))\(s\)/g- rzeczywisty wzorzec do wyszukiwania ( amount object(s))
  • (_,a)=>a- _jest zmienną typu catch all, ajest(\S+ +(\S+))
  • "s"[+/^(1|one|an?)/i.test(a)]||""- zamiast kroić tablicę, po prostu utwórz tablicę zastępczą i uzyskaj indeks ( +/.../.testzwraca liczbę)
    • powinien "s"[+/^(1|one|an?)/i.test(a)]zwrócić undefined( truelub 1test) powrócić""
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.