Supprimer des éléments uniques de la chaîne

12

Je suis tombé sur cette question, car il semble que ce soit un cas d'utilisation très courant pour trouver des caractères uniques dans une chaîne. Mais que faire si on veut s'en débarrasser?

L'entrée ne contient que des alphabets en minuscules. Seules les lettres de a à z sont utilisées. La longueur d'entrée peut être comprise entre 1 et 1 000 caractères.

Exemple:
entrée: helloworld
sortie: llool

Objectif: Le code le plus court gagne
Langue: N'importe lequel des 20 meilleurs langages TIOBE

user14742
la source

Réponses:

7

Perl, 28 24 caractères (dont 1 pour l'option 'p')

s/./$&x(s!$&!$&!g>1)/eg

Usage:

> perl -pe 's/./$&x(s!$&!$&!g>1)/eg'
helloworld
llool

Au début, je pensais que je pouvais le faire avec un regard négatif et un regard négatif derrière, mais il s'avère que les regards négatifs doivent avoir une longueur fixe. J'ai donc opté pour des expressions rationnelles imbriquées à la place. Merci à mob pour l' $&astuce.

Gareth
la source
+1. J'ai pensé naïvement que je pourrais prendre cette chose avec ma réponse Ruby.
Steven Rumbalski
J'ai essayé cela sur du texte chinois et ça n'a pas fait l'affaire. = (
ixtmixilix
@ixtmixilix - puis exécutez perl avec l' -CDSoption
mob
@ixtmixilix Je ne connais pas suffisamment l'Unicode et son support par Perl pour suggérer un moyen de le faire fonctionner avec du texte chinois. Heureusement pour moi, la question ne dit que les minuscules de a à z.
Gareth
1
Remplacez tous les $1par $&et vous risquez de perdre quelques paires de parenthèses.
mob
12

(GolfScript, 15 13 caractères)

:;{.;?);>?)},

GolfScript n'est pas l'un des 20 meilleurs, mais un golf de code sans GolfScript ... ( exécutez-le vous-même )

Version précédente: ( exécuter le script )

1/:;{;\-,;,(<},
Howard
la source
1
:;? Vous essayez délibérément de confondre les débutants, n'est-ce pas? ;)
Peter Taylor
@PeterTaylor Vous avez raison. J'aurais dû choisir un )- ça en ferait un smiley alors :). Malheureusement, je n'ai pas trouvé de moyen d'éliminer même le chiffre 1. (Remarque pour les débutants de GolfScript: vous pouvez remplacer tout ;dans le code par un x(ou toute autre lettre ou chiffre - ou tout caractère non utilisé dans le script autrement). Dans ce cas particulier, ce ;n'est qu'un nom de variable - et n'a pas la signification de "pop and discard". Dans GolfScript, presque tous les jetons sont des variables de toute façon, et l'utilisation de symboles prédéfinis est un excellent moyen de rendre les scripts encore plus illisibles pour les étrangers ;-).)
Howard
Une autre solution de 13 caractères::a{]a.@--,(},
Ilmari Karonen
7

J, 12 caractères

Après avoir entré une réponse Perl valide, voici une réponse invalide (langue qui ne fait pas partie du top 20 de TIOBE).

a=:#~1<+/@e.

Usage:

   a 'helloworld'
llool

Déclare un verbe aqui ne produit que des éléments non uniques.

Gareth
la source
5

GolfScript (14 caractères)

:x{{=}+x\,,(},

Démo en ligne

Peut-être pas qualifié pour gagner, mais il est utile d'avoir un critère.

Peter Taylor
la source
4

Rubis 46 40 36

gets.chars{|c|$><<c if$_.count(c)>1}
Steven Rumbalski
la source
Vous pouvez enregistrer 4 caractères si vous êtes en ligne set utilisez $_pour la deuxième apparence (l'espace avant est alors disponible).
Howard
@Howard: Belle prise. Merci. J'ai environ zéro expérience avec Ruby.
Steven Rumbalski
2

Perl 44

$l=$_;print join"",grep{$l=~/$_.*$_/}split""

Exécution:

perl -lane '$l=$_;print join"",grep{$l=~/$_.*$_/}split""' <<< helloworld
llool
flodel
la source
2

K, 18

{x@&x in&~1=#:'=x}
tmartin
la source
Vous pouvez enregistrer un octet en utilisant 1<#au lieu de~1=#
J. Sendra
2

Python 2.7 ( 52 51), Python 3 (52)

Je ne m'attendais pas à ce que ce soit si court.

2.7: a=raw_input();print filter(lambda x:a.count(x)>1,a)

3.0: a=input();print''.join(i for i in a if a.count(x)>1)

raw_input(): stocke l'entrée sous forme de chaîne ( input()= eval(raw_input()))
(Python 3.0: input()a été transformé en raw_input())

filter(lambda x:a.count(x)>1,a): Filtrez tous les personnages à l'intérieur as'ils se trouvent dans aplusieurs fois ( a.count(x)>1).

beary605
la source
Si vous utilisez python 3 à la place, vous pouvez utiliser input()plutôt que raw_input(). Bien que vous deviez ajouter un caractère pour une parenthèse fermante, puisqu'il prints'agit d'une fonction en python 3.
Strigoides
@Strigoides: J'ai ajouté un extrait de code Python 3 à ma réponse.
beary605
Le filtre de Python 3 renvoie un itérateur ... Vous devrez le faire''.join(...)
JBernardo
@JBernardo: :( Dang. Merci de m'avoir prévenu. Comme vous pouvez le voir, je n'utilise pas 3.0.
beary605
2

sed et coreutils (128)

Certes, cela ne fait pas partie de la liste TIOBE, mais c'est amusant (-:

<<<$s sed 's/./&\n/g'|head -c -1|sort|uniq -c|sed -n 's/^ *1 (.*)/\1/p'|tr -d '\n'|sed 's:^:s/[:; s:$:]//g\n:'|sed -f - <(<<<$s)

Version sans golf:

s=helloworld
<<< $s sed 's/./&\n/g'        \
| head -c -1                  \
| sort                        \
| uniq -c                     \
| sed -n 's/^ *1 (.*)/\1/p'   \
| tr -d '\n'                  \
| sed 's:^:s/[:; s:$:]//g\n:' \
| sed -f - <(<<< $s)

Explication

Le premier sed convertit l'entrée en un caractère par ligne. Le deuxième sed trouve des personnages qui n'apparaissent qu'une seule fois. Troisième sed écrit un script sed qui supprime des caractères uniques. Le dernier sed exécute le script généré.

Thor
la source
2

Brachylog (v2), 8 octets

⊇.oḅlⁿ1∧

Essayez-le en ligne!

Soumission de fonction. Techniquement non compétitif car la question a une limite sur les langages autorisés à concourir (cependant, plusieurs autres réponses ont déjà ignoré la restriction).

Explication

⊇.oḅlⁿ1∧
⊇         Find {the longest possible} subset of the input
  o       {for which after} sorting it,
   ḅ        and dividing the sorted input into blocks of identical elements,
    lⁿ1     the length of a resulting block is never 1
 .     ∧  Output the subset in question.
ais523
la source
Pourquoi avez-vous CW toutes vos solutions?
Shaggy
1
@Shaggy: a) parce que je suis d'accord avec les autres personnes qui les éditent, b) pour éviter de gagner en réputation s'ils sont surévalués. En général, je pense que la gamififcation de Stack Exchange est un énorme détriment pour le site - il y a parfois une corrélation négative entre les actions que vous pouvez entreprendre pour améliorer la réputation et les actions que vous pouvez entreprendre pour réellement améliorer le site. De plus, être à un niveau de réputation élevé est nul. le site ne cesse de vous harceler pour effectuer des tâches d'administration, et tout ce que vous faites est un instrument contondant (par exemple, lorsque vous êtes à faible répétition, vous pouvez suggérer une modification, à haute répétition, il est simplement forcé).
ais523
2

Japt , 6 5 octets

ÆèX É

-1 octet grâce à @Oliver

Essayez-le en ligne!

Quintec
la source
2
Bienvenue chez Japt! Il existe en fait un raccourci pour o@:Æ
Oliver
@Oliver Un autre raccourci que j'ai manqué, cool, merci :)
Quintec
@Oliver, la meilleure question est de savoir comment je l'ai raté?! : \
Shaggy
1

Python (56)

Voici une autre alternative (quelques caractères de plus) en Python:

a=raw_input();print''.join(c for c in a if a.count(c)>1)

Si vous acceptez la sortie sous forme de liste (par exemple ['l', 'l', 'o', 'o', 'l']), nous pourrions la résumer à 49 caractères:

a=raw_input();print[c for c in a if a.count(c)>1]
arshajii
la source
Hé, >1c'est une bonne idée! Puis-je intégrer cela dans ma solution?
beary605
@ beary605 Bien sûr, pas de problème du tout - moyen facile de couper un personnage: D
arshajii
1

Mathematica 72 63

Ok, Mathematica ne fait pas partie des 20 meilleures langues, mais j'ai quand même décidé de rejoindre la fête.

x est la chaîne d'entrée.

"" <> Select[y = Characters@x, ! MemberQ[Cases[Tally@y, {a_, 1} :> a], #] &]
DavidC
la source
1

Perl (55)

@x=split//,<>;$s{$_}++for@x;for(@x){print if($s{$_}>1)}

Lit à partir de stdin.

QuasarDonkey
la source
1

C # - 77 caractères

Func<string,string>F=s=>new string(s.Where(c=>s.Count(d=>c==d)>1).ToArray());

Si vous acceptez la sortie sous forme de tableau, elle se résume à 65 caractères:

Func<string,char[]>F=s=>s.Where(c=>s.Count(d=>c==d)>1).ToArray();
Mormegil
la source
1

Ocaml, 139 133

Utilise ExtString.String d'ExtLib

open ExtString.String
let f s=let g c=fold_left(fun a d->a+Obj.magic(d=c))0 s in replace_chars(fun c->if g c=1 then""else of_char c)s

Version non golfée

open ExtString.String
let f s =
  let g c =
    fold_left
      (fun a c' -> a + Obj.magic (c' = c))
      0
      s
  in replace_chars
  (fun c ->
    if g c = 1
    then ""
    else of_char c)
  s

La fonction grenvoie le nombre d'occurrences de c dans la chaîne s. La fonction fremplace tous les caractères par la chaîne vide ou la chaîne contenant le caractère en fonction du nombre d'occurrences. Edit: j'ai raccourci le code de 6 caractères en abusant de la représentation interne des bools :-)

Oh, et ocaml est 0 sur l'indice TIOBE ;-)

ReyCharles
la source
f *** l'indice TIOBE.
ixtmixilix
Je suis d'accord. Merci aussi pour le vote positif. Maintenant, je peux commenter :-)
ReyCharles
1

PHP - 70

while($x<strlen($s)){$c=$s[$x];echo substr_count($s,$c)>1?$c:'';$x++;}

avec une hypothèse $ s = 'helloworld'.

hengky mulyono
la source
1

Java 8, 90 octets

s->{for(char c=96;++c<123;s=s.matches(".*"+c+".*"+c+".*")?s:s.replace(c+"",""));return s;}

Explication:

Essayez-le en ligne.

s->{                         // Method with String as both parameter and return-type
  for(char c=96;++c<123;     //  Loop over the lowercase alphabet
    s=s.matches(".*"+c+".*"+c+".*")?
                             //   If the String contains the character more than once
       s                     //    Keep the String as is
      :                      //   Else (only contains it once):
       s.replace(c+"",""));  //    Remove this character from the String
  return s;}                 //  Return the modified String
Kevin Cruijssen
la source
1

PowerShell , 59 octets

"$args"-replace"[^$($args|% t*y|group|?{$_.Count-1}|% n*)]"

Essayez-le en ligne!

Moins golfé:

$repeatedСhars=$args|% toCharArray|group|?{$_.Count-1}|% name
"$args"-replace"[^$repeatedСhars]"

Remarque: $repeatedCharsest un tableau. Par défaut, un Powershell joint les éléments du tableau par un caractère d'espace tout en convertissant le tableau en chaîne. Ainsi, l'expression rationnelle contient des espaces (dans cet exemple, [^l o]). Les espaces n'affectent pas le résultat car la chaîne d'entrée contient uniquement des lettres.

mazzy
la source
1

APL (Dyalog Extended) , 8 octets SBCS

Fonction de préfixe tacite anonyme.

∊⊢⊆⍨1<⍧⍨

Essayez-le en ligne!

⍧⍨ compte selfie (compte les occurrences des éléments d'argument dans l'argument lui-même)

1< Masque booléen où l'on est inférieur à celui

⊢⊆⍨ partitionner l'argument par ce masque (en commençant une nouvelle partition sur 1s et en supprimant sur 0s)

ϵ nlist (aplatir)

Adam
la source
1

JavaScript, 45 octets

s=>[...s].filter(c=>s.match(c+'.*'+c)).join``
kamoroso94
la source
1

R , 70 octets

a=utf8ToInt(scan(,''));intToUtf8(a[!a%in%names(table(a)[table(a)<2])])

Essayez-le en ligne!

Une mauvaise tentative, même à partir d'un top 20 des langues TIOBE. Je sais que quelque chose peut être fait au cours de la seconde moitié, mais pour le moment, aucun golf ne m'échappe.

Sumner18
la source
0

PHP - 137

Code

implode('',array_intersect(str_split($text),array_flip(array_filter(array_count_values(str_split($text)),function($x){return $x>=2;}))));

Code normal

$text   = 'helloworld';
$filter = array_filter(array_count_values(str_split($text)), function($x){return $x>=2;});
$output = implode('',array_intersect(str_split($text),array_flip($filter)));

echo $output;
Wahyu Kristianto
la source
0

PHP - 83 78

<?for($a=$argv[1];$i<strlen($a);$r[$a[$i++]]++)foreach($ras$k=>$c)if($c>1)echo$k

Version améliorée:

<?for($s=$argv[1];$x<strlen($s);$c=$s[$x++]) echo substr_count($s,$c)>1?$c:'';

Bien sûr, cela nécessite la désactivation des notifications

Éditer: Amélioration inspirée par @hengky mulyono

Je suis si mauvais au codegolf :)

milo5b
la source
0

C ++, 139 octets

string s;cin>>s;string w{s}; auto l=remove_if(begin(s),end(s),[&w](auto&s){return count(begin(w),end(w),s)==1;});s.erase(l,end(s));cout<<s;

non golfé:

#include <algorithm>
#include <string>
#include <iostream>

int main() {
  using namespace std;
  string s;
  cin >> s;
  const string w{s};
  auto l = remove_if(begin(s), end(s), [&w](auto& s) {
                                         return count(begin(w), end(w), s) == 1;
                                       });
  s.erase(l, end(s));
  cout << s;
  return 0;
}
zelcon
la source