Rimuovi il / i plurale / i ambiguo / i!


21

La programmazione è molto rigida. Non puoi dire a un programma di "emettere il conteggio delle banane", devi dirlo a print(bananas).

Ma quando lo fai, ti ritrovi con un problema: non sai quante banane hai in anticipo, quindi non sai se usare un plurale.

A volte, i programmatori diventano pigri. Invece di controllare, stampano solo there are X banana(s).

Ma è brutto, quindi abbiamo bisogno di un programma per risolvere questo problema.

I metodi

Per rimuovere i plurali ambigui in una stringa, attenersi alla seguente procedura:

  1. Dividi la stringa sugli spazi in un elenco di parole.

  2. Per ogni parola che termina con (s), procedi come segue:

    • Se la parola precedente è a, an, 1o one, rimuovere il (s)alla fine della parola.
    • Altrimenti, se la parola è la prima parola della stringa o la parola precedente non è a, an, 1o one, sostituire il (s)alla fine della parola con s.
  3. Unisci nuovamente l'elenco di parole in una stringa, preservando lo spazio bianco originale.

Esempio (s)

Prendiamo una corda there's a banana(s) and three apple(s).

Innanzitutto, dividiamo la stringa in un elenco di parole: ["there's", "a", "banana(s)", "and", "three", "apple(s)"]

Per il secondo passo, prendiamo le due parole che terminano con (s): banana(s)e apple(s).

La parola prima banana(s)è a, quindi rimuoviamo il (s), facendolo banana. La parola prima apple(s)è three, quindi cambiamo il (s)in s, così diventa apples.

Ora abbiamo ["there's", "a", "banana", "and", "three", "apples"]. Unendo nuovamente l'elenco, otteniamo there's a banana and three apples. Questo è il nostro risultato finale.

Le sfide)

Creare un programma o una funzione che accetta una stringa ambigua in qualsiasi formato ragionevole e restituisce la versione non ambigua di quella stringa.

Puoi presumere che la stringa non contenga nuove righe, tabulazioni o ritorni a capo.

Ho dimenticato di specificare se dividere su gruppi di spazi o spazi (cioè se okay thencon due spazi dovrebbe essere ["okay", "then"]o ["okay", "", "then"]) quando si pubblica la sfida, quindi è possibile assumere entrambe le forme di divisione.

Casi 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

punteggio

Dato che si tratta di , vince l'invio con il minor numero di byte!


Questa domanda è stata sandbox .
Lirico:

Dovrebbe invece apple(s)cedere il caso di test apples? La sfida afferma Otherwise, if the word is the first word in the string . . . replace the (s) at the end of the word with s.che noto che questo caso ha ceduto applesalla sandbox per le prime tre revisioni, ma è cambiato alla quarta.
fireflame241

@ fireflame241 Quando scrivevo la seconda bozza delle regole, l'avrei fatto in modo che l'inizio della stringa fosse invariato. Ho modificato quella regola in seguito, ma non il caso di test. Buona pesca.
Lirico

Suggerimento del test: There's a single banana(s)-> There's a single bananas.
Jonathan Allan,

1
@JonathanAllan Non puoi. Aggiungerò alcuni casi di test.
Lirico

Risposte:


6

Mathematica, 151 148 byte

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

Spiegazione

j=" ";k=Except@j

Impostato jsu uno o più caratteri bianchi. Impostare ksul modello "non j" (= carattere non bianco).

j<>j<>#<>j

Prepara due spazi bianchi e aggiungi uno o più spazi bianchi all'input.

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

Per una sottostringa che corrisponde al modello:

  1. Uno spazio (i), seguito da
  2. una sottostringa di lunghezza zero o più lunga composta solo da caratteri non bianchi (quantificatore) (chiamare questo a), seguito da
  3. una sottostringa long-one o più lunga composta solo da uno o più caratteri di spazio (chiamare questo s), seguita da
  4. una sottostringa lunghezza-uno o più lunga composta solo da caratteri non bianchi (parola) (parola) (chiamata così w), seguita da
  5. la stringa "(s)", seguita da
  6. uno o più spazi bianchi
Se [FreeQ [a, "a" | "un" | "1" | "uno"], "s", ""]

Se anon è una o più delle parole singolari, valuta "s"altrimenti "".

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

Sostituire il pattern matching con j, a, s, w, If[FreeQ[a,"a"|"an"|"1"|"one"],"s",""], e juniti.

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

Prendi dalla posizione 3 alla posizione -2 (1-indicizzato; gli indici negativi contano dalla fine). Questo perché abbiamo aggiunto tre spazi all'inizio.


3
Perché non usare l'integrato per rimuovere il plural-S?
Thomas Weller,

5

Python 3 , 94 byte

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

Provalo online!

-4 byte grazie a cri everytim (penso che questo sia accettabile)


@JonathanAllan Risolto, grazie.
HyperNeutrino,

1
__import__non può essere più breve ... Sì, è 4 byte più corto di un normale import re.
totalmente umano

@icrieverytim eh hai ragione (solo 3 byte però) grazie
HyperNeutrino


@icrieverytim ._. Oh bello. Grazie!
HyperNeutrino


4

Mathematica, 313 byte

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

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

Abbina ogni (s)alla fine della parola, sostituiscilo con !$1(1 o 0) esses.


2

Pyth - 53 byte

Segue l'algoritmo praticamente così com'è.

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

Provalo online qui .


1
Errore there are two banana(s) and one leprechaun(s)(due spazi dopo il one). Lo spazio bianco originale viene conservato, ma leprechaun(s)ignora il oneprecedente.
Lirico:

1
@LyricLy non l'hai esplicitamente dichiarato nel PO. Con due spazi (usando (1) la sezione "metodo (i)" di "dividi la stringa sugli spazi in un elenco di parole") c'è in realtà una parola vuota tra oneeleprechaun(s)
Jonathan Allan

2

Gelatina ,  52 51  49 byte

Jelly non ha un atomo regex (s)

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

Un programma completo che accetta una stringa (usando la formattazione Python se multilinea o contenente virgolette) e stampa l'output.

Provalo online! o vedi la suite di test .

Come?

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

Sono curioso di sapere perché hai usato come link separato. Questo impedisce di eliminare l'elemento dall'elenco originale?
HyperNeutrino,

No, devo prendere la coda della coppia ... scrivere un commento in codice, forse puoi vedere un golf una volta che lo vedi.
Jonathan Allan,

Ah ok. Grazie, proverò a individuare il golf una volta che c'è un commento (o prima di allora)!
HyperNeutrino,

Quindi i collegamenti 1, 2 e 3 in coda, e il collegamento 5 sceglie quale chiamare e usa Ŀper farlo, ma non vedo un modo breve per mettere in coda il collegamento 4, ma potrebbe esserci. Potrebbe anche esserci un modo per inserire la coda del link 4!
Jonathan Allan,

@HyperNeutrino Penso che la Ŀcosa possa chiamare il primo link, ecco perché è un link a sé stante.
Erik the Outgolfer,


1

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

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

Provalo online!


1
Non sui casi di test, ma penso che questo fallisca a hel(s)lo.
Neil,

Funziona correttamente come previsto nel test case. È vicino alla parte inferiore dei casi di test nel mio link TIO.
Xcali,

Bene, dovrò solo essere a hel(s)loaggiunto ai casi di test, e quindi forse aggiusterai il tuo codice ...
Neil,

0

JavaScript (ES6), 88 87 byte

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

Spiegazione in arrivo.


1
puoi sostituire \scon `` secondo "Puoi presumere che la stringa non contenga nuove righe, tabulazioni o ritorni a capo."
SuperStormer

Non riesce su "this is a te (s) t". È possibile risolvere aggiungendo (\s|$)alla fine del regex.
Birjolaxew,

Inoltre non riesce su "apple (s)". Risolto in questo TIO
Birjolaxew il

Grazie @Birjolaxew, modificherò le modifiche quando posso ...
XavCo7

0

JavaScript (ES6), 84 byte

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

Ecco un modo interessante per riorganizzare l'ultima parte, che è purtroppo più lunga di 2 byte:

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

0

JavaScript (SpiderMonkey) , 82 byte

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

Provalo online!

Versione a 78 byte (meno robusta)

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

Questa è una versione modificata di ETHproductions '(non ho 50 rep.)

Spiegazione

  • /(\S+ +(\S+))\(s\)/g- il modello reale da cercare ( amount object(s))
  • (_,a)=>a- _è un problema tutto variabile, aè il(\S+ +(\S+))
  • "s"[+/^(1|one|an?)/i.test(a)]||""- Invece di tagliare la matrice, basta creare una matrice fittizia e ottenere l'indice ( +/.../.testrestituisce un numero)
    • dovrebbe "s"[+/^(1|one|an?)/i.test(a)]restituire undefined( trueo 1per il test) ritorno""
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.