Trova la stringa originale, senza la ripetizione senza la ripetizione nel mezzo


25

A volte capita che durante la digitazione di una frase, mi distraggo e finisco per digitare le stesse coppie di parole due volte due parole due volte consecutive.

Per assicurarti che le altre persone non siano infastidite da questo, il tuo compito è scrivere un programma che risolva questo problema!

Compito

Data una stringa di input (se è importante per la tua lingua, puoi assumere un input solo ASCII che non contiene avanzamenti di riga) str, che contiene da qualche parte nel mezzo una sottostringa che si verifica due volte in successione immediata, restituisci la stringa con un'istanza di questo sottostringa rimossa.

Nel caso di più possibilità, restituire la risposta più breve possibile (ovvero, selezionare la sottostringa ripetuta consecutiva più lunga e rimuoverla).

Nel caso di più sottostringhe consecutive consecutive ugualmente lunghe, rimuovere la prima (ovvero la prima rilevata durante la lettura della stringa da davanti a dietro).

Si può presumere che l'input sia corretto (cioè contiene sempre una sottostringa ripetuta consecutiva), il che potrebbe aiutare a ridimensionarlo.


Esempi

  1. Ingresso: hello hello world-> Output: hello world.
  2. Ingresso: foofoo-> Output: foo. (Quindi: Sì, la stringa potrebbe consistere solo nella parte ripetuta due volte).
  3. Input: aaaaa-> Output:, aaapoiché la sottostringa consecutiva ripetuta più lunga è qui aa.
  4. Input: Slartibartfast-> Questo non è un input valido, poiché non contiene una sottostringa ripetuta consecutiva, quindi non è necessario gestire questo caso.
  5. Input: the few the bar-> Questo è un altro input non valido, poiché la parte ripetuta dovrebbe seguire immediatamente la parte originale. In questo caso, thee thesono separati da qualcos'altro nel mezzo, quindi questo input non è valido.
  6. Ingresso: ababcbc-> Output: abcbc. Le due sottostringhe ripetute consecutive più lunghe possibili sono abe bc. Come abgià riscontrato nella stringa, questa è la risposta corretta.
  7. Ingresso: Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo. Uscita: Buffalo buffalo buffalo buffalo Buffalo buffalo. (La sostituzione eseguita deve essere sensibile al maiuscolo / minuscolo).
  8. Ingresso: Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice couple of words twice in succession.-> Output: Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. Viene rimossa solo la sottostringa ripetuta consecutiva più lunga.

Il codice dovrebbe essere il più breve possibile, poiché si tratta di , quindi vince la risposta più breve in byte. In bocca al lupo!


@manatwork Quando si prende la prima frase, ovvero Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice couple of words twice in succession.come input, l'output dovrebbe essere Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. Viene rimossa solo la duplicazione trovata più a lungo.
Qqwy

1
Suggerisco di aggiungere un test con due possibili sostituzioni, in cui il secondo è più lungo del primo. Sospetto che la maggior parte delle risposte non la supererà :)
circa il

@aross test case 8 è esattamente questo :)
Qqwy

A meno che io e il mio codice di prova non ci sbagliassimo, c'è solo una stringa ripetuta.
circa l'

@aross c'è un doppio pinhappens
Qqwy

Risposte:


8

Perl 6 , 40 byte

{.subst: m:ex/(.*))>$0/.max(*.chars),''}

Provalo

{
  .subst:             # substitute


    m                 # match
    :exhaustive
    /
      ( .* )          # any number of chars

      )>              # don't include the following in what is returned

      $0              # the first match again
    /.max( *.chars ), # find the first longest submatch


    ''                # substitute it with nothing
}

8

Retina , 35 33 byte

Il conteggio dei byte presuppone la codifica ISO 8859-1.

(?=(.+)(\1.*))
$2¶$`
O$#`
$.&
G1`

Provalo online!

Spiegazione

Poiché i motori regex cercano partite da sinistra a destra, non è banale trovare la partita più lunga indipendentemente dalla posizione. Può essere fatto con i gruppi di bilanciamento di .NET, ma il risultato è piuttosto spiacevolmente lungo:

1`((.)+)\1(?<=(?!.*((?>(?<-2>.)+).+)\3)^.*)
$1

Quindi ho pensato di provare a evitarlo facendo uso di alcune altre funzionalità di Retina.

(?=(.+)(\1.*))
$2¶$`

Iniziamo applicando essenzialmente tutte le possibili sostituzioni, una su ogni riga. Per fare ciò, abbiniamo la posizione di fronte a una partita (invece della partita stessa), per consentire le partite sovrapposte. Questo viene fatto mettendo la vera regex in uno sguardo. Quel lookahead quindi cattura il rimanente tranne il duplicato che vogliamo rimuovere nel gruppo 2. Scriviamo di nuovo il gruppo 2 (eliminando il duplicato), un avanzamento di riga e quindi l'intero input fino alla corrispondenza, che ci dà sostanzialmente una nuova riga per essere sostituito.

Alla fine avremo una riga per ogni partita, con il duplicato corrispondente rimosso. Alla fine ci sarà anche di nuovo l'input completo senza alcuna sostituzione.

Ora che abbiamo tutte le possibili sostituzioni, vogliamo il risultato più breve (che corrisponde alla ripetizione rimossa più a lungo).

O$#`
$.&

Quindi prima ordiniamo le linee per lunghezza.

G1`

E poi manteniamo solo la prima riga.


Caspita, quella tecnica di sostituzione è davvero intelligente!
Leone

6

Gelatina , 22 19 byte

-2 byte grazie a Dennis (evitare un'inversione di argomento, rimuovere l'incremento sottilmente ridondante)

ẋ2³wȧ+¥J
ẆÇ€LÐṀḢṬœp

Provalo online!

Programma completo (è stato trovato un errore nel ÐṀnon agire con la correttezza aritica sulle diadi, che verrà risolto presto; anche se non sono sicuro che qui si possa ottenere un codice più corto).

Come?

Trova la prima delle sezioni più lunghe dell'input in modo che esista una ripetizione nell'input e la rimuove dall'input.

ẋ2³wȧ+¥J - Link 1, removal indices for given slice if valid, else 0: slice, x
ẋ2       - repeat x twice, say y
  ³      - program input: s
   w     - index of first occurrence of y in s (1-based) or 0, say i
       J - range(length(x)): [1,2,3,...,length(x)]
      ¥  - last two links as a dyad
    ȧ    -     and (non-vectorising)
     +   -     addition: [1+i,2+i,3+i,...,length(x)+i] or 0
         - note: no need to decrement these since the last index will be the 1st index
         - of the repetition (thanks to Dennis for spotting that!)

ẆÇ€LÐṀḢṬœp - Main link: string, s
Ẇ          - all sublists of s (order is short to long, left to right, e.g. a,b,c,ab,bc,abc)
 Ç€        - call the last link (1) as a monad for €ach
    ÐṀ     - filter by maximal
   L       -     length
      Ḣ    - head: get the first (and hence left-most) one
       Ṭ   - untruth: make a list with 1s at the indexes given and 0s elsewhere
        œp - partition s at truthy indexes of that, throwing away the borders
           - implicit print

6

JavaScript (ES6), 81 74 byte

f=
s=>s.replace(/(?=(.+)\1)/g,(_,m)=>r=m[r.length]?m:r,r='')&&s.replace(r,'')
<input oninput=o.textContent=f(this.value)><pre id=o>

Modifica: salvato 7 byte rubando il m[r.length]trucco di @Arnauld.


5

PowerShell , 87 byte

param($s)([regex](([regex]'(.+)\1'|% *hes $s|sort L*)[-1]|% Gr*|% V*)[1])|% Re* $s '' 1

Provalo online! (tutti i casi di test)

Spiegazione

Partendo dall'interno fondamentalmente, corriamo Matchescon (.+)\1regex, per restituire tutti gli oggetti match per la stringa specificata. La regex corrisponde a qualsiasi sequenza di caratteri seguita da sé.

Quindi gli oggetti di corrispondenza risultanti vengono convogliati sortper essere ordinati in base alla loro Lengthproprietà (abbreviata in carattere jolly). Ciò si traduce in una serie di corrispondenze ordinate per lunghezza, crescente, quindi indicizza con [-1]per ottenere l'ultimo elemento (il più lungo). Il valore di quella corrispondenza è però la corrispondenza, non il gruppo, quindi include la ripetizione, quindi recuperiamo l'oggetto Gruppo ( |% Gr*) e quindi il valore di quello ( |% V*) per ottenere la stringa ripetuta più grande. La cosa è che l'oggetto gruppo è in realtà un array perché il gruppo 0 è sempre la corrispondenza, ma voglio il gruppo effettivo (1), quindi il valore risultante è in realtà valore s , quindi indicizzazione per ottenere il secondo elemento [1]. Questo valore viene lanciato su un oggetto regex stesso e quindi suReplaceIl metodo viene chiamato rispetto alla stringa originale, sostituendo con nulla e viene sostituita solo la prima corrispondenza ( |% Re* $s '' 1).


5

Haskell , 101 byte

La funzione principale è f, prende e restituisce a String.

l=length
a=splitAt
f s|i<-[0..l s-1]=[p++t|n<-i,(p,(r,t))<-fmap(a$l s-n).(`a`s)<$>i,r==take(l r)t]!!0

Provalo online!

Quando ho iniziato questo, ho importato Data.Liste utilizzato maximum, tails, initse isPrefixOf. In qualche modo questo si è trasformato in questo. Ma sono riuscito a radere solo 11 byte ...

Gli appunti

  • splitAt/ adivide una stringa in un determinato indice.
  • s è la stringa di input.
  • iè l'elenco di numeri [0 .. length s - 1], -1è quello di aggirare che si splitAtdivide alla fine se viene dato un indice troppo grande.
  • nè length smeno l'obiettivo di lunghezza corrente per la parte ripetuta, è scelto in questo modo, quindi non dobbiamo usare due elenchi di numeri e / o la sintassi dettagliata dell'elenco decrescente.
  • p, re tsono una divisione a tre di s, con rla parte ripetuta prevista. Il fmaplà utilizza il (,) String Functorper evitare una variabile per una divisione intermedia.
  • !!0 seleziona il primo elemento dell'elenco di corrispondenze.


4

Mathematica, 63 60 59 byte

4 byte salvati grazie a Martin Ender .

#&@@StringReplaceList[#,a__~~a__->a]~SortBy~{StringLength}&

Funzione anonima. Accetta una stringa come input e restituisce una stringa come output.


Questo non sembra funzionare sull'esempio 6 - ~SortBy~StringLengthordina le stringhe in ordine alfabetico se le loro lunghezze sono uguali ...
Non un albero

1
@ LegionMammal978 La correzione più breve è mantenere SortBye avvolgere StringLengthin un elenco per ottenere un ordinamento stabile.
Martin Ender,

3

JavaScript (ES6), 70 byte

s=>s.replace(s.match(/(.+)(?=\1)/g).reduce((p,c)=>c[p.length]?c:p),'')

Casi test


Non funziona aaaabaaab, ma è un buon uso di reduce.
Neil

2

Questo dovrebbe essere un commento, ma non ho abbastanza reputazione per commentare. Voglio solo dire a @Neil che il suo codice può essere ridotto a 77 byte. Non è necessario utilizzare l'asserzione diretta in regex. Ecco la versione ridotta:

s=>s.replace(/(.+)\1/g,(_,m)=>(n=m.length)>l&&(l=n,r=m),l=0)&&s.replace(r,'')

2
Ciao e benvenuto in PPCG! Puoi inviarlo come risposta JavaScript personale! Se lo desideri, posso modificare il tuo post e mostrarti come dovrebbe apparire.
NoOneIsHere

2
Devo usare l'affermazione diretta per affrontare il caso di partite sovrapposte. aababè l'esempio più breve di dove il tuo suggerimento fallisce.
Neil

0

C #, 169 byte

(s)=>{var x="";for(int i=0;i<s.Length-2;i++){for(int l=1;l<=(s.Length-i)/2;l++){var y=s.Substring(i,l);if(s.Contains(y+y)&l>x.Length)x=y;}}return s.Replace(x+x,x);}

Spiegazione

(s) => {                // Anonymous function declaration    
    var x = "";         // String to store the longest repeating substring found
    for (int i = 0; i < s.Length - 2; i++) {               // Loop through the input string
        for (int l = 1; l <= (s.Length - i) / 2; l++) {    // Loop through all possible substring lengths
            var y = s.Substring(i, l);
            if (s.Contains(y + y) & l > x.Length) x = y;   // Check if the substring repeats and is longer than any previously found
        }
    }
    return s.Replace(x + x, x);    // Perform the replacement
}

Questo è l'approccio a forza bruta: provare ogni sottostringa possibile fino a quando non troviamo la sottostringa ripetuta più lunga. Indubbiamente Regex è più efficiente, ma trattare con Regex in C # tende ad essere abbastanza dettagliato.


Benvenuti in PPCG! Tutte le risposte devono essere programmi completi o funzioni richiamabili , non certo frammenti con input in variabili hardcoded. Inoltre, mostra la versione del codice che hai effettivamente contato con tutti gli spazi bianchi non necessari rimossi. Puoi sempre includere la versione più leggibile con rientro oltre a quella completamente giocata a golf.
Martin Ender,

0

PHP, 84 82 byte

Nota: utilizza la codifica IBM-850.

for($l=strlen($argn);--$l&&!$r=preg_filter("#(.{0$l})\g-1#",~█╬,$argn,1););echo$r;

Esegui in questo modo:

echo 'hello hello world' | php -nR 'for($l=strlen($argn);--$l&&!$r=preg_filter("#(.{0$l})\g-1#",~█╬,$argn,1););echo$r;';echo
> hello world

Spiegazione

for(
  $l=strlen($argn);   # Set $l to input length.
  --$l   &&           # Decrement $l each iteration until it becomes 0.
  !$r=preg_filter(    # Stop looping when preg_filter has a result
                      # (meaning a successful replace).
    "#(.{0$l})\g-1#", # Find any character, $l times (so the longest
                      # match is tried first), repeated twice.
    ~█╬,              # Replace with $1: first capture group, removing the
                      # duplicate.
    $argn,
    1                 # Only replace 1 match.
  );
);
echo$r;               # Print the result of the (only) successful
                      # search/replace, if any.

Ritocchi

  • Salvato 2 byte perché non esiste una lunghezza minima della sottostringa ripetuta
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.