Trouvez la chaîne d'origine, sans la répétition sans la répétition au milieu

25

Parfois, il arrive qu'en tapant une phrase, je suis distrait et je finis par taper deux fois de suite le même couple de mots deux fois de suite.

Pour vous assurer que les autres personnes ne sont pas gênées par cela, votre tâche consiste à écrire un programme qui résout ce problème!

Tâche

Étant donné une chaîne d'entrée (si cela est important pour votre langue, vous pouvez supposer une entrée ASCII uniquement qui ne contient pas de sauts de ligne.) str, Qui contient quelque part en son milieu une sous-chaîne qui se produit deux fois de suite immédiatement, renvoyez la chaîne avec une instance de ceci sous-chaîne supprimée.

Dans le cas de plusieurs possibilités, renvoyez la réponse la plus courte possible (c'est-à-dire, choisissez la sous-chaîne répétitive consécutive la plus longue et supprimez-la).

Dans le cas de plusieurs sous-chaînes répétitives consécutives de longueur égale, supprimez la première (c'est-à-dire la première rencontrée lors de la lecture de la chaîne d'avant en arrière).

Vous pouvez supposer que l'entrée est correcte (c'est-à-dire qu'elle contient toujours une sous-chaîne répétée consécutive), ce qui pourrait aider à la réduire.


Exemples

  1. Entrée: hello hello world-> Sortie: hello world.
  2. Entrée: foofoo-> Sortie: foo. (Donc: oui, la chaîne peut ne se composer que de la partie répétée deux fois).
  3. Entrée: aaaaa-> Sortie:, aaacar la plus longue sous-chaîne répétée consécutive est ici aa.
  4. Entrée: Slartibartfast-> Ce n'est pas une entrée valide, car elle ne contient pas de sous-chaîne répétitive consécutive, vous n'avez donc pas besoin de gérer ce cas.
  5. Entrée: the few the bar-> Ceci est une autre entrée non valide, car la partie répétitive doit suivre immédiatement la partie d'origine. Dans ce cas, theet thesont séparés par quelque chose d'autre entre eux, donc cette entrée n'est pas valide.
  6. Entrée: ababcbc-> Sortie: abcbc. Les deux sous-chaînes répétitives consécutives les plus longues possibles sont abet bc. Comme abon le rencontre plus tôt dans la chaîne, celle-ci est la bonne réponse.
  7. Entrée: Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo. Sortie: Buffalo buffalo buffalo buffalo Buffalo buffalo. (Le remplacement effectué doit être sensible à la casse).
  8. Entrée: 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.-> Sortie: Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. Seule la plus longue sous-chaîne répétée consécutive est supprimée.

Votre code doit être aussi court que possible, car il s'agit de , donc la réponse la plus courte en octets l'emporte. Bonne chance!

Qqwy
la source
@manatwork Lorsque vous prenez la première phrase, c'est-à-dire 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.en entrée, la sortie doit être Sometimes it happens that while typing a sentence, I am distracted and I end up typing the same couple of words twice in succession.. Seule la duplication trouvée la plus longue est supprimée.
Qqwy
1
Je suggère d'ajouter un test qui a deux remplacements possibles, où le second est plus long que le premier. Je soupçonne que la plupart des réponses ne passeront pas qu'un :)
aross
@aross test case 8 est exactement ça :)
Qqwy
À moins que mon code de test et moi ne nous trompions, il n'y a qu'une seule chaîne répétée.
2017
@aross il y a un double penhappens
Qqwy

Réponses:

8

Perl 6 , 40 octets

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

Essayez-le

{
  .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
}
Brad Gilbert b2gills
la source
8

Rétine , 35 33 octets

Le nombre d'octets suppose un codage ISO 8859-1.

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

Essayez-le en ligne!

Explication

Étant donné que les moteurs d'expression régulière recherchent des correspondances de gauche à droite, il n'est pas trivial de trouver la correspondance la plus longue quelle que soit la position. Cela peut être fait avec les groupes d'équilibrage de .NET, mais le résultat est plutôt désagréablement long:

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

J'ai donc pensé que j'essaierais d'éviter cela en utilisant d'autres fonctionnalités Retina.

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

Nous commençons par appliquer essentiellement toutes les substitutions possibles, une sur chaque ligne. Pour ce faire, nous faisons correspondre la position devant une correspondance (au lieu de la correspondance elle-même), pour permettre des correspondances qui se chevauchent. Cela se fait en mettant le vrai regex dans une anticipation. Ce lookahead capture ensuite le reste, sauf le doublon que nous voulons supprimer dans le groupe 2. Nous réécrivons le groupe 2 (suppression du doublon), un saut de ligne, puis toute l'entrée jusqu'à la correspondance, ce qui nous donne essentiellement une nouvelle ligne pour être substitué.

À la fin, nous aurons une ligne pour chaque correspondance, le doublon correspondant étant supprimé. À la fin, il y aura également une entrée complète à nouveau sans aucune substitution.

Maintenant que nous avons toutes les substitutions possibles, nous voulons le résultat le plus court (ce qui correspond à la répétition supprimée la plus longue).

O$#`
$.&

Nous trions donc d'abord les lignes par longueur.

G1`

Et puis on ne garde que la première ligne.

Martin Ender
la source
Wow, cette technique de remplacement est vraiment intelligente!
Leo
6

Gelée , 22 19 octets

-2 octets grâce à Dennis (éviter une inversion d'argument, supprimer l'incrément subtilement redondant)

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

Essayez-le en ligne!

Programme complet (un bug a été trouvé avec le fait de ÐṀne pas agir avec l'arité correcte sur les dyades, qui sera bientôt corrigé; bien que je ne suis pas sûr que cela puisse rendre le code plus court ici).

Comment?

Recherche la première des tranches les plus longues de l'entrée de sorte qu'une répétition existe dans l'entrée et la supprime de l'entrée.

ẋ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
Jonathan Allan
la source
6

JavaScript (ES6), 81 74 octets

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>

Edit: sauvé 7 octets en volant le m[r.length]truc de @ Arnauld .

Neil
la source
5

PowerShell , 87 octets

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

Essayez-le en ligne! (tous les cas de test)

Explication

En partant de l'intérieur, nous exécutons Matchesavec l' (.+)\1expression régulière, pour renvoyer tous les objets de correspondance pour la chaîne spécifiée. L'expression régulière correspond à n'importe quelle séquence de caractères qui est suivie par elle-même.

Les objets de correspondance résultants sont ensuite redirigés sortpour être triés selon leur Lengthpropriété (raccourci en caractère générique). Il en résulte un tableau de correspondances triées par longueur, croissant, donc indexez avec [-1]pour obtenir le dernier élément (le plus long). La valeur de cette correspondance est cependant la correspondance, pas le groupe, donc elle inclut la répétition, nous récupérons donc l'objet Group ( |% Gr*), puis la valeur de that ( |% V*) pour obtenir la plus grande chaîne répétée. La chose est que l'objet groupe est en fait un tableau parce que le groupe 0 est toujours la correspondance, mais je veux le groupe réel (1), donc la valeur résultante est en fait la valeur s , donc l'indexation pour obtenir le deuxième élément [1]. Cette valeur est convertie en un objet regex lui-même, puis leReplaceest appelée par rapport à la chaîne d'origine, en la remplaçant par rien, et seule la première correspondance est remplacée ( |% Re* $s '' 1).

briantiste
la source
5

Haskell , 101 octets

La fonction principale est f, il prend et retourne 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

Essayez-le en ligne!

Quand j'ai commencé, j'importé Data.Listet utilisé maximum, tails, initset isPrefixOf. D'une manière ou d'une autre, cela s'est transformé en ceci. Mais je n'ai réussi à raser que 11 octets ...

Remarques

  • splitAt/ adivise une chaîne à un index donné.
  • s est la chaîne d'entrée.
  • iest la liste des nombres [0 .. length s - 1], -1c'est de contourner cela qui splitAtse divise à la fin si on lui donne un index trop grand.
  • nest length smoins l'objectif de longueur actuel pour la partie répétée, il est choisi de cette façon afin que nous n'ayons pas à utiliser deux listes de nombres et / ou la syntaxe de liste décroissante détaillée.
  • p, rEt tsont une fraction à trois voies de s, avec rla partie destinée répétée. Le fmapil utilise le (,) String Functorpour éviter une variable pour un fractionnement intermédiaire.
  • !!0 sélectionne le premier élément de la liste des correspondances.
Ørjan Johansen
la source
4

Gelée , 23 21 octets

ṚẆUẋ€2ẇÐf¹ṪðLHḶ+w@Ṭœp

Merci à @JonathanAllan pour son Ṭœpidée qui a permis d'économiser 2 octets.

Essayez-le en ligne!

Dennis
la source
4

Mathematica, 63 60 59 octets

4 octets enregistrés grâce à Martin Ender .

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

Fonction anonyme. Prend une chaîne en entrée et renvoie une chaîne en sortie.

LegionMammal978
la source
Cela ne semble pas fonctionner sur l'exemple 6 - ~SortBy~StringLengthtrie les chaînes par ordre alphabétique si leurs longueurs sont les mêmes ...
Pas un arbre
1
@ LegionMammal978 La solution la plus courte consiste à conserver SortByet à envelopper StringLengthdans une liste pour obtenir un tri stable.
Martin Ender
3

JavaScript (ES6), 70 octets

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

Cas de test

Arnauld
la source
Échoue aaaabaaab, mais bonne utilisation de reduce.
Neil
2

Cela devrait être un commentaire, mais je n'ai pas assez de réputation pour commenter. Je veux juste dire à @Neil que son code peut être réduit à 77 octets. Vous n'avez pas besoin d'utiliser l'assertion directe dans l'expression régulière. Voici la version réduite:

s=>s.replace(/(.+)\1/g,(_,m)=>(n=m.length)>l&&(l=n,r=m),l=0)&&s.replace(r,'')
TRОLL
la source
2
Bonjour et bienvenue chez PPCG! Vous pouvez soumettre ceci comme votre propre réponse JavaScript! Si vous le souhaitez, je peux modifier votre message et vous montrer à quoi il devrait ressembler.
NoOneIsHere
2
J'ai besoin d'utiliser l'assertion directe pour traiter le cas de correspondances qui se chevauchent. aababest l'exemple le plus court de l'échec de votre suggestion.
Neil
0

C #, 169 octets

(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);}

Explication

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

C'est l'approche par force brute: essayez toutes les sous-chaînes possibles jusqu'à ce que nous trouvions la sous-chaîne répétitive la plus longue. Sans aucun doute, Regex est plus efficace, mais traiter avec Regex en C # a tendance à être assez verbeux.

Extragorey
la source
Bienvenue chez PPCG! Toutes les réponses doivent être des programmes complets ou des fonctions appelables , pas des extraits sûrs avec des entrées dans des variables codées en dur. En outre, veuillez montrer la version du code que vous avez réellement compté avec tous les espaces inutiles supprimés. Vous pouvez toujours inclure la version plus lisible avec indentation en plus de celle entièrement jouée.
Martin Ender
0

PHP, 84 82 octets

Remarque: utilise le codage IBM-850.

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

Courez comme ceci:

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

Explication

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.

Tweaks

  • Enregistré 2 octets car il n'y a pas de longueur minimale de la sous-chaîne répétée
aross
la source