Supprimez les pluriels ambigus!

21

La programmation est très rigide. Vous ne pouvez pas dire à un programme de "sortir le nombre de bananes", vous devez le lui dire print(bananas).

Mais lorsque vous faites cela, vous vous retrouvez avec un problème: vous ne savez pas combien de bananes vous avez à l'avance, donc vous ne savez pas si vous devez utiliser un pluriel.

Parfois, les programmeurs vont paresseusement. Au lieu de vérifier, ils impriment simplement there are X banana(s).

Mais c'est moche, nous avons donc besoin d'un programme pour résoudre ce problème.

Les méthodes)

Pour supprimer les pluriels ambigus d'une chaîne, procédez comme suit:

  1. Divisez la chaîne des espaces en une liste de mots.

  2. Pour chaque mot qui se termine par (s), procédez comme suit:

    • Si le mot précédent est a, an, 1ou one, retirer la (s)fin du mot.
    • Dans le cas contraire, si le mot est le premier mot dans la chaîne ou le mot précédent est pas a, an, 1ou one, remplacer la (s)fin du mot s.
  3. Rejoins la liste des mots dans une chaîne, en préservant les espaces d'origine.

Exemples)

Prenons une chaîne there's a banana(s) and three apple(s).

Tout d'abord, nous avons divisé la chaîne en une liste de mots: ["there's", "a", "banana(s)", "and", "three", "apple(s)"]

Pour la deuxième étape, nous prenons les deux mots se terminant par (s): banana(s)et apple(s).

Le mot avant banana(s)est a, donc nous supprimons le (s), ce qui en fait banana. Le mot avant apple(s)est three, donc nous changeons le (s)en s, ainsi il devient apples.

Nous avons maintenant ["there's", "a", "banana", "and", "three", "apples"]. Rejouer la liste ensemble, nous obtenons there's a banana and three apples. Ceci est notre résultat final.

Les défis)

Créez un programme ou une fonction qui prend une chaîne ambiguë dans n'importe quel format raisonnable et renvoie la version non ambiguë de cette chaîne.

Vous pouvez supposer que la chaîne ne contient aucun retour à la ligne, tabulation ou retour chariot.

J'ai oublié de préciser si de diviser les groupes d'espaces ou des espaces ( à savoir si okay thenavec deux espaces doivent être ["okay", "then"]ou ["okay", "", "then"]) lors de la publication du défi, de sorte que vous pouvez prendre soit sous forme de division.

Cas de test

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

Notation

Comme c'est du , la soumission avec le moins d'octets gagne!

LyricLy
la source
Cette question a été mise en bac à sable .
LyricLy
Le scénario de apple(s)test devrait- il applesplutôt céder ? Le défi indique que Otherwise, if the word is the first word in the string . . . replace the (s) at the end of the word with s.je note que cette affaire a cédé applesen bac à sable pour les trois premières révisions mais a changé à la quatrième.
fireflame241
@ fireflame241 Lors de l'écriture du deuxième brouillon des règles, j'allais faire en sorte que le début de la chaîne reste inchangé. J'ai changé cette règle plus tard, mais pas le cas de test. Bonne prise.
LyricLy
Suggestion de cas de test: There's a single banana(s)-> There's a single bananas.
Jonathan Allan
1
@JonathanAllan Vous ne pouvez pas. J'ajouterai quelques cas de test.
LyricLy

Réponses:

6

Mathematica, 151 148 octets

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

Explication

j=" ";k=Except@j

Défini jsur un ou plusieurs espaces. Définissez kle modèle "not j" (= caractère non blanc).

j<>j<>#<>j

Ajoutez deux espaces blancs et ajoutez un espace blanc à l'entrée.

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

Pour une ou des sous-chaînes correspondant au motif:

  1. Un ou plusieurs espaces, suivi de
  2. une sous-chaîne de longueur zéro ou plus longue composée uniquement de caractères non blancs (quantificateur) (appelez cela a), suivi de
  3. une sous-chaîne de longueur un ou plus longue composée uniquement de caractères d'espacement (appelez cela s), suivie de
  4. une sous-chaîne de longueur un ou plus longue composée uniquement de caractères non blancs (mot) (appelez cela w), suivi de
  5. la chaîne "(s)", suivie de
  6. un ou des espaces
Si [FreeQ [a, "a" | "an" | "1" | "one"], "s", ""]

Si an'est pas l'un des mots singuliers, évaluez à "s", sinon "".

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

Remplacer la configuration d'adaptation avec j, a, s, w, If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""], et jreliés entre eux.

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

Passer de la position 3 à la position -2 (1 indexé; les indices négatifs comptent à partir de la fin). C'est parce que nous avons ajouté trois espaces au début.

JungHwan Min
la source
3
Pourquoi ne pas utiliser la fonction intégrée pour supprimer le pluriel-S?
Thomas Weller
5

Python 3 , 94 octets

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

Essayez-le en ligne!

-4 octets grâce à i cri everytim (je pense que c'est acceptable)

HyperNeutrino
la source
@JonathanAllan Fixed, merci.
HyperNeutrino
1
__import__ne peut pas être plus court ... Ouais, c'est 4 octets plus court comme un régulier import re.
2017 totalement humain
@icrieverytim hein, vous avez raison (seulement 3 octets cependant) merci
HyperNeutrino
attendez pas voici 94
totalement humain
@icrieverytim ._. Oh sympa. Merci!
HyperNeutrino
4

Rétine , 53 octets

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

Essayez-le en ligne!

fireflame241
la source
1
Cela supprime l'espace après banana(s)dans there's a banana(s) and three apple(s)- essayez ce correctif
Neil
Vous pouvez passer a|anà an?-1 octet
PunPun1000
4

Mathematica, 313 octets

(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
la source
3

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

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

Correspond à chaque (s)fin de mot, remplacez-le par !$1(1 ou 0) esses.

Basse
la source
2

Pyth - 53 octets

Suit l'algorithme à peu près tel qu'il est.

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

Essayez-le en ligne ici .

Maltysen
la source
1
Échoue there are two banana(s) and one leprechaun(s)(deux espaces après le one). L'espace d'origine est conservé, mais leprechaun(s)ignore le oneprécédent.
LyricLy
1
@LyricLy vous ne l'avez pas explicitement indiqué dans le PO. Avec deux espaces (en utilisant (1) de votre section "méthode (s)" de "diviser la chaîne sur les espaces en une liste de mots"), il y a en fait un mot vide entre oneetleprechaun(s)
Jonathan Allan
2

Gelée ,  52 51  49 octets

Jelly n'a pas d'atome de regex (s)

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

Un programme complet acceptant une chaîne (utilisant le formatage Python si multiligne ou contenant des guillemets) et imprimant la sortie.

Essayez-le en ligne! ou voir la suite de tests .

Comment?

Ṫ - 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
la source
Je suis curieux de savoir pourquoi vous avez utilisé un lien distinct. Cela empêche-t-il de supprimer l'élément de la liste d'origine?
HyperNeutrino
Non, je dois obtenir la queue de la paire ... rédiger un commentaire de code, peut-être que vous pourrez repérer un golf une fois que vous aurez vu cela.
Jonathan Allan
Ah ok. Merci, je vais essayer de repérer le golf une fois qu'il y aura un commentaire (ou avant)!
HyperNeutrino
Ainsi, les liens 1, 2 et 3 sont tous de queue, et le lien 5 choisit lequel appeler et utilise Ŀpour le faire, mais je ne vois pas de moyen court de suivre à l'intérieur du lien 4, mais il pourrait y en avoir. Il pourrait même y avoir un moyen d'y mettre la queue du lien 4!
Jonathan Allan
@HyperNeutrino Je pense que le Ŀbidule peut appeler le premier lien, c'est pourquoi c'est un lien à lui tout seul.
Erik the Outgolfer du 1er
1

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

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

Essayez-le en ligne!

Xcali
la source
1
Pas sur les cas de test, mais je pense que cela échoue a hel(s)lo.
Neil
Cela fonctionne correctement comme prévu dans le cas de test. C'est près du bas des cas de test dans mon lien TIO.
Xcali
Eh bien, je vais juste devoir être a hel(s)loajouté aux cas de test, et puis peut-être que vous corrigerez votre code ...
Neil
0

JavaScript (ES6), 88 87 octets

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

Explication à venir.

XavCo7
la source
1
vous pouvez remplacer \spar `` selon "Vous pouvez supposer que la chaîne ne contient aucun retour à la ligne, tabulation ou retour chariot."
SuperStormer
Échoue sur "c'est un te (s) t". Vous pouvez résoudre ce problème en ajoutant (\s|$)à la fin de l'expression régulière.
Birjolaxew
Échoue également sur "pomme (s)". Corrigé dans ce TIO
Birjolaxew
Merci @Birjolaxew, éditerai les changements quand je pourrai ...
XavCo7
0

JavaScript (ES6), 84 octets

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

Voici une façon intéressante de réorganiser la dernière partie, qui est malheureusement de 2 octets de plus:

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

JavaScript (SpiderMonkey) , 82 octets

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

Essayez-le en ligne!

Version 78 octets (moins robuste)

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

Ceci est une version modifiée de ETHproductions '(je n'ai pas 50 rep.)

Explication

  • /(\S+ +(\S+))\(s\)/g- le motif réel à rechercher ( amount object(s))
  • (_,a)=>a- _est une variable catch all, aest la(\S+ +(\S+))
  • "s"[+/^(1|one|an?)/i.test(a)]||""- au lieu de découper le tableau, créez simplement un tableau factice et obtenez l'index ( +/.../.testretourne un nombre)
    • devrait "s"[+/^(1|one|an?)/i.test(a)]retourner undefined( true, ou 1pour le test)""
Ephellon Dantzler
la source