Mehrdeutige Plural (e) entfernen!

21

Die Programmierung ist sehr starr. Sie können einem Programm nicht sagen, dass es die Bananenzählung ausgeben soll. Sie müssen es dazu auffordern print(bananas).

Aber wenn Sie das tun, haben Sie ein Problem: Sie wissen vorher nicht, wie viele Bananen Sie haben, also wissen Sie nicht, ob Sie einen Plural verwenden sollen.

Manchmal gehen Programmierer den faulen Weg. Anstatt zu prüfen, drucken sie einfach there are X banana(s).

Aber das ist hässlich, also brauchen wir ein Programm, um das zu beheben.

Die Methoden)

Gehen Sie folgendermaßen vor, um die mehrdeutigen Pluralformen in einer Zeichenfolge zu entfernen:

  1. Teilen Sie die Zeichenfolge auf Leerzeichen in eine Liste von Wörtern.

  2. Führen Sie für jedes Wort, das mit endet (s), Folgendes aus:

    • Wenn das vorhergehende Wort a, an, 1oder one, entfernen Sie die (s)am Ende des Wortes.
    • Andernfalls, wenn das Wort das erste Wort in der Kette ist , oder das vorhergehende Wort nicht a, an, 1oder oneersetzt die (s)am Ende des Wortes mit s.
  3. Fügen Sie die Liste der Wörter wieder zu einer Zeichenfolge zusammen, wobei das ursprüngliche Leerzeichen erhalten bleibt.

Beispiel (e)

Nehmen wir eine Zeichenfolge there's a banana(s) and three apple(s).

Zuerst teilen wir die Zeichenfolge in eine Liste von Wörtern auf: ["there's", "a", "banana(s)", "and", "three", "apple(s)"]

Für den zweiten Schritt nehmen wir die zwei Wörter, die mit (s): banana(s)und enden apple(s).

Das Wort davor banana(s)ist a, also entfernen wir das (s), machen es banana. Das Wort davor apple(s)ist three, also ändern wir das (s)zu s, so wird es apples.

Wir haben jetzt ["there's", "a", "banana", "and", "three", "apples"]. Wenn wir die Liste wieder zusammenfügen, bekommen wir there's a banana and three apples. Dies ist unser Endergebnis.

Die Herausforderungen)

Erstellen Sie ein Programm oder eine Funktion, die eine mehrdeutige Zeichenfolge in einem angemessenen Format verwendet und die nicht mehrdeutige Version dieser Zeichenfolge zurückgibt.

Sie können davon ausgehen, dass die Zeichenfolge keine Zeilenumbrüche, Tabulatoren oder Zeilenumbrüche enthält.

Ich habe vergessen, beim Posten der Challenge anzugeben, ob eine Aufteilung nach Gruppen von Räumen oder Räumen (dh okay thenmit zwei Räumen) erfolgen soll ["okay", "then"]oder nicht ["okay", "", "then"].

Testfall (e)

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

Wertung

Da es sich um , Bytes die Vorlage mit dem geringsten gewinnt!

Textlich
quelle
Diese Frage wurde mit einem Sandkasten versehen .
LyricLy
Sollte der apple(s)Testfall applesstattdessen nachgeben ? Die Herausforderung besagt Otherwise, if the word is the first word in the string . . . replace the (s) at the end of the word with s., dass ich bemerke, dass dieser Fall applesin den ersten drei Revisionen im Sandkasten nachgab, sich aber beim vierten geändert hat.
Fireflame241
@ fireflame241 Beim Schreiben des zweiten Entwurfs der Regeln wollte ich dafür sorgen, dass der Anfang der Zeichenfolge unverändert bleibt. Ich habe diese Regel später geändert, aber nicht den Testfall. Guter Fang.
Text
Testfallvorschlag: There's a single banana(s)-> There's a single bananas.
Jonathan Allan
1
@ JonathanAllan Sie können nicht. Ich werde ein paar Testfälle hinzufügen.
Text

Antworten:

6

Mathematica, 151–148 Bytes

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

Erläuterung

j=" ";k=Except@j

Auf jLeerzeichen setzen. Stellen Sie kdas Muster "not j" (= Nicht-Leerzeichen) ein.

j<>j<>#<>j

Stellen Sie zwei Leerzeichen voran und fügen Sie ein Leerzeichen an die Eingabe an.

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

Für eine Teilzeichenfolge, die dem Muster entspricht:

  1. Ein Leerzeichen, gefolgt von
  2. Eine Teilzeichenfolge mit der Länge Null oder länger, die nur aus Nicht-Leerzeichen (Quantifizierer) besteht (nennen Sie dies a), gefolgt von
  3. ein Teilstring der Länge eins oder länger, der nur aus Leerzeichen besteht (nennen Sie dies s), gefolgt von
  4. ein Teilstring der Länge eins oder länger, der nur aus Nicht-Leerzeichen (Word) besteht (nennen Sie dies w), gefolgt von
  5. die Zeichenfolge "(s)", gefolgt von
  6. ein Leerzeichen
Wenn [FreeQ [a, "a" | "eine" | "1" | "eins"], "s", ""]

Wenn aes sich nicht um ein einzelnes Wort handelt, bewerten Sie es mit "s", andernfalls mit "".

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

Ersetzen der Übereinstimmungsmuster mit j, a, s, w, If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""], und jmiteinander verbunden sind .

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

Nehmen Sie von Position 3 bis Position -2 (1-indiziert; negative Indizes zählen vom Ende). Dies liegt daran, dass wir am Anfang drei Leerzeichen hinzugefügt haben.

JungHwan min
quelle
3
Warum nicht das eingebaute zum Entfernen von Plural-S verwenden?
Thomas Weller
5

Python 3 , 94 Bytes

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

Probieren Sie es online!

-4 bytes dank i cri everytim (ich denke das ist akzeptabel)

HyperNeutrino
quelle
@ JonathanAllan Behoben, danke.
HyperNeutrino
1
__import__kann unmöglich kürzer sein ... Yup, es ist 4 Bytes kürzer als ein normaler import re.
Totalhuman
@icrieverytim huh du hast recht (nur 3 Bytes) danke
HyperNeutrino
@icrieverytim ._. Oh schön. Vielen Dank!
HyperNeutrino
4

Netzhaut , 53 Bytes

(( |^)(a|an|1|one) [^ ]*)\(s\)( |$)
$1
\(s\)( |$)
s$1

Probieren Sie es online!

fireflame241
quelle
1
Dies löscht den Raum nach banana(s)in there's a banana(s) and three apple(s)- versuchen dieses Update
Neil
Sie können ändern , a|anum an?für -1 Byte
PunPun1000
4

Mathematica, 313 Bytes

(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)&
J42161217
quelle
3

Perl 5, 43 + 1 (-p) = 44 Bytes

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

Passen Sie jedes (s)Wort am Ende an und ersetzen Sie es durch !$1(1 oder 0).

Bass
quelle
2

Pyth - 53 Bytes

Folgt dem Algorithmus so ziemlich wie er ist.

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

Probieren Sie es hier online aus .

Maltysen
quelle
1
Scheitert an there are two banana(s) and one leprechaun(s)(zwei Leerzeichen nach dem one). Das ursprüngliche Leerzeichen bleibt erhalten, leprechaun(s)ignoriert jedoch das vorangegangene one.
Text
1
@LyricLy Sie haben dies im OP nicht explizit angegeben. Mit zwei Leerzeichen (unter Verwendung von (1) Ihres Abschnitts "Methode (n)" unter "Teilen Sie die Zeichenfolge auf Leerzeichen in eine Liste von Wörtern") gibt es tatsächlich ein leeres Wort zwischen oneundleprechaun(s)
Jonathan Allan
2

Jelly ,  52 51  49 Bytes

Jelly hat kein einziges Regex-Atom

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

Ein vollständiges Programm, das eine Zeichenfolge akzeptiert (mit Python-Formatierung, wenn es mehrzeilig ist oder Anführungszeichen enthält) und die Ausgabe druckt.

Probieren Sie es online! oder sehen Sie sich die Testsuite an .

Wie?

Ṫ - 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
Jonathan Allan
quelle
Ich bin gespannt, warum Sie als separaten Link verwendet haben. Verhindert dies das Löschen des Elements aus der ursprünglichen Liste?
HyperNeutrino
Nein, ich muss den Schwanz des Paares herausfinden ... indem ich einen Codekommentar schreibe, können Sie vielleicht einen Golf entdecken, wenn Sie das sehen.
Jonathan Allan
Ah okay. Danke, ich werde versuchen, den Golf zu erkennen, sobald es einen Kommentar gibt (oder vorher)!
HyperNeutrino
Die Links 1, 2 und 3 sind alle Endstücke, und Link 5 wählt die aufzurufenden Elemente aus und verwendet Ŀdiese, aber ich sehe keinen kurzen Weg zum Endstück in Link 4, aber möglicherweise gibt es einen. Es könnte sogar eine Möglichkeit geben, den Schwanz von Link 4 auch dort rein zu bekommen!
Jonathan Allan
@HyperNeutrino Ich denke, dass das ĿDing den ersten Link nennen kann, deshalb ist ein Link für sich.
Erik der Outgolfer
1

Perl 5 , 56 + 1 ( -p) = 57 Bytes

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

Probieren Sie es online!

Xcali
quelle
1
Nicht in den Testfällen, aber ich denke, das schlägt fehl a hel(s)lo.
Neil
Das funktioniert einwandfrei wie im Testfall vorgesehen. Es befindet sich in meinem TIO-Link am Ende der Testfälle.
Xcali
Nun, ich muss nur a hel(s)lonoch zu den Testfällen hinzugefügt werden, und dann reparierst du vielleicht deinen Code ...
Neil,
0

JavaScript (ES6), 88 87 Bytes

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

Erklärung folgt in Kürze.

XavCo7
quelle
1
Sie können \smit `` ersetzen, entsprechend "Sie können davon ausgehen, dass die Zeichenfolge keine Zeilenumbrüche, Tabulatoren oder Zeilenumbrüche enthält."
SuperStormer
Scheitert an "this is a te (s) t". Sie können (\s|$)das Problem beheben, indem Sie am Ende des regulären Ausdrucks hinzufügen .
Birjolaxew
Scheitert auch an "Apfel (en)".
Behoben
Danke @Birjolaxew, werde die Änderungen bearbeiten, wenn ich kann ...
XavCo7
0

JavaScript (ES6), 84 Byte

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

Hier ist eine interessante Möglichkeit, den letzten Teil, der leider 2 Bytes länger ist, neu anzuordnen:

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

JavaScript (SpiderMonkey) , 82 Byte

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

Probieren Sie es online!

78 Byte Version (weniger robust)

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

Dies ist eine modifizierte Version von ETHproductions '(ich habe keine 50 Repräsentanten)

Erläuterung

  • /(\S+ +(\S+))\(s\)/g- das aktuelle Muster, nach dem gesucht werden soll ( amount object(s))
  • (_,a)=>a- _Ist ein catch all variabel, aist das(\S+ +(\S+))
  • "s"[+/^(1|one|an?)/i.test(a)]||""- anstatt das Array aufzuteilen, mache einfach ein Dummy-Array und erhalte den Index ( +/.../.testgibt eine Zahl zurück)
    • sollte "s"[+/^(1|one|an?)/i.test(a)]zurückkehren undefined( trueoder 1für den Test) zurückkehren""
Ephellon Dantzler
quelle