Usuwanie unikatowych elementów z łańcucha

12

Natknąłem się na to pytanie, ponieważ wydaje się, że bardzo częstym przypadkiem jest znajdowanie unikatowych znaków w łańcuchu. Ale co, jeśli chcemy się ich pozbyć?

Dane wejściowe zawierają tylko małe litery. Używane są tylko litery od a do z. Długość wejściowa może wynosić od 1 do 1000 znaków.

Przykład:
input: helloworld
output: llool

Cel: Wygrywa najkrótszy kod
Język: Jeden z 20 najlepszych języków TIOBE

użytkownik14742
źródło

Odpowiedzi:

7

Perl, 28 24 znaków (zawiera 1 dla opcji „p”)

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

Stosowanie:

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

Na początku myślałem, że mogę to zrobić z negatywnym spojrzeniem w przyszłość i negatywnym spojrzeniem w tył, ale okazuje się, że negatywne spojrzenia w tył muszą mieć ustaloną długość. Zamiast tego wybrałem zagnieżdżone wyrażenia regularne. Dzięki mobowi za $&wskazówkę.

Gareth
źródło
+1. Naiwnie myślałem, że mogę wziąć to z moją odpowiedzią Ruby.
Steven Rumbalski,
próbowałem tego na chińskim tekście i to nie załatwiło sprawy. = (
ixtmixilix
@ixtmixilix - następnie uruchom perla z -CDSopcją
mob
@ixtmixilix Nie wiem wystarczająco dużo o Unicode i wsparciu Perla, aby zaproponować sposób, aby działał z chińskim tekstem Obawiam się. Na szczęście dla mnie pytanie brzmi tylko małe litery od a do z.
Gareth,
1
Wymień wszystkie $1z $&i można stracić kilka par nawiasów.
tłum
12

(GolfScript, 15 13 znaków)

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

GolfScript nie jest jednym z 20 najlepszych, ale golfem bez GolfScript ... ( uruchom go sam )

Poprzednia wersja: ( uruchom skrypt )

1/:;{;\-,;,(<},
Howard
źródło
1
:;? Celowo próbujesz zmylić początkujących, prawda? ;)
Peter Taylor,
@PeterTaylor Masz rację. Powinienem był wybrać )- to uczyniłoby to buźkę :). Niestety nie znalazłem sposobu na wyeliminowanie cyfry 1. (Uwaga dla początkujących w GolfScript: możesz zamienić dowolny ;kod w kodzie na x(lub dowolną inną literę lub cyfrę - lub dowolny znak, który nie zostałby użyty w skrypcie w inny sposób). W tym szczególnym przypadku ;jest to tylko nazwa zmiennej - i nie ma ona znaczenia „pop and discard”. W GolfScript prawie wszystkie tokeny i tak są zmienne, a użycie predefiniowanych symboli jest świetnym sposobem na uczynienie skryptów jeszcze bardziej nieczytelnymi dla osób postronnych ;-).)
Howard,
Kolejne 13-znakowe rozwiązanie::a{]a.@--,(},
Ilmari Karonen,
7

J, 12 znaków

Po wprowadzeniu prawidłowej odpowiedzi w Perlu, oto niepoprawna (język nie znajduje się w pierwszej 20 TIOBE).

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

Stosowanie:

   a 'helloworld'
llool

Deklaruje czasownik, aktóry wyświetla tylko nie unikalne elementy.

Gareth
źródło
5

GolfScript (14 znaków)

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

Demo online

Może nie kwalifikuje się do wygrania, ale warto mieć miernik.

Peter Taylor
źródło
4

Rubinowy 46 40 36

gets.chars{|c|$><<c if$_.count(c)>1}
Steven Rumbalski
źródło
Możesz zapisać 4 znaki, jeśli wstawisz si użyjesz $_dla drugiego wyglądu (wówczas miejsce przedtem jest wtedy zbędne).
Howard,
@ Howard: Niezły chwyt. Dzięki. Mam prawie zerowe doświadczenie z Ruby.
Steven Rumbalski,
2

Perl 44

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

Wykonanie:

perl -lane '$l=$_;print join"",grep{$l=~/$_.*$_/}split""' <<< helloworld
llool
flodel
źródło
2

K, 18 lat

{x@&x in&~1=#:'=x}
tartin
źródło
Możesz zapisać bajt, używając 1<#zamiast~1=#
J. Sendra
2

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

Nie spodziewałem się, że będzie tak krótki.

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(): przechowuj dane wejściowe jako ciąg ( input()= eval(raw_input()))
(Python 3.0: input()został przekształcony raw_input())

filter(lambda x:a.count(x)>1,a): Filtruj wszystkie znaki znajdujące się wewnątrz, ajeśli występują w awięcej niż jeden raz ( a.count(x)>1).

beary605
źródło
Jeśli zamiast tego używasz Pythona 3, możesz użyć input()zamiast raw_input(). Chociaż musisz dodać jeden znak do nawiasu zamykającego, ponieważ printjest to funkcja w python 3.
Strigoides
@ Strigoides: Dodałem fragment kodu Python 3 do mojej odpowiedzi.
beary605
Filtr Pythona 3 zwraca iterator ... Musisz to zrobić''.join(...)
JBernardo,
@JBernardo: :( Dang. Dziękuję za powiadomienie. Jak widać, nie używam 3.0.
beary605
2

sed i coreutils (128)

To prawda, że ​​nie jest to część listy TIOBE, ale jest zabawne (-:

<<<$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)

Wersja bez golfa:

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)

Wyjaśnienie

Pierwszy sed przekształca dane wejściowe w jeden znak w wierszu. Drugi sed znajduje znaki, które występują tylko raz. Trzeci sed pisze skrypt sed, który usuwa unikalne znaki. Ostatni sed wykonuje wygenerowany skrypt.

Thor
źródło
2

Brachylog (v2), 8 bajtów

⊇.oḅlⁿ1∧

Wypróbuj online!

Podanie funkcji. Technicznie niekonkurencyjne, ponieważ pytanie ma ograniczenia dotyczące tego, jakie języki mogą konkurować (jednak kilka innych odpowiedzi już zignorowało to ograniczenie).

Wyjaśnienie

⊇.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
źródło
Dlaczego korzystasz z wszystkich swoich rozwiązań?
Kudłaty
1
@Shaggy: a) ponieważ nie mam nic przeciwko edytowaniu ich przez innych ludzi, b) aby uniknąć zyskiwania reputacji, jeśli zostaną pochwalone. Ogólnie myślę, że grywalizacja Stack Exchange stanowi ogromną szkodę dla strony - czasami istnieje negatywna korelacja między działaniami, które możesz podjąć w celu poprawy rep, a działaniami, które możesz podjąć, aby faktycznie ulepszyć witrynę. Dodatkowo bycie cieszącym się dobrą reputacją jest do bani; strona wciąż nęka cię do wykonywania zadań administracyjnych, a wszystko, co robisz, jest tępym narzędziem (np. gdy jesteś w niskiej liczbie powtórzeń, możesz zasugerować edycję, w wysokiej powtórce jest to po prostu wymuszane).
ais523,
2

Japt , 6 5 bajtów

ÆèX É

-1 bajt dzięki @Oliver

Wypróbuj online!

Quintec
źródło
2
Witamy w Japt! Istnieje skrót do o@:Æ
Oliver,
@Oliver Kolejny skrót, za którym tęskniłem, fajnie, dziękuję :)
Quintec
@Oliver, tym lepsze pytanie brzmi jak Feck nie mogę przegapić ?! : \
Shaggy
1

Python (56)

Oto kolejna (kilka znaków dłuższa) alternatywa w Pythonie:

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

Jeśli zaakceptujesz wynik jako listę (np. ['l', 'l', 'o', 'o', 'l']), Możemy sprowadzić go do 49 znaków:

a=raw_input();print[c for c in a if a.count(c)>1]
arshajii
źródło
Hej, >1to dobry pomysł! Czy mogę to włączyć do mojego rozwiązania?
beary605
@ beary605 Na pewno nie ma problemu - łatwy sposób na przycięcie postaci: D
arshajii
1

Mathematica 72 63

Ok, Mathematica nie należy do 20 najpopularniejszych języków, ale i tak zdecydowałem się dołączyć.

x jest łańcuchem wejściowym.

"" <> Select[y = Characters@x, ! MemberQ[Cases[Tally@y, {a_, 1} :> a], #] &]
DavidC
źródło
1

Perl (55)

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

Czyta ze standardowego.

QuasarDonkey
źródło
1

C # - 77 znaków

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

Jeśli zaakceptujesz wynik jako tablicę, sprowadza się on do 65 znaków:

Func<string,char[]>F=s=>s.Where(c=>s.Count(d=>c==d)>1).ToArray();
Mormegil
źródło
1

Ocaml, 139 133

Używa ExtString.String 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

Wersja bez golfa

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

Funkcja gzwraca liczbę wystąpień c w ciągu s. Ta funkcja fzastępuje wszystkie znaki albo pustym łańcuchem, albo łańcuchem zawierającym znak, w zależności od liczby wystąpień. Edycja: Skróciłem kod o 6 znaków, nadużywając wewnętrznej reprezentacji booli :-)

Aha, a ocaml ma wartość 0 w indeksie TIOBE ;-)

ReyCharles
źródło
f *** indeks TIOBE.
ixtmixilix
Zgadzam się. Dziękuję również za poparcie. Teraz mogę komentować :-)
ReyCharles,
1

PHP - 70

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

z założeniem $ s = „helloworld”.

hengky mulyono
źródło
1

Java 8, 90 bajtów

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

Wyjaśnienie:

Wypróbuj online.

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
źródło
1

PowerShell , 59 bajtów

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

Wypróbuj online!

Mniej golfa:

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

Uwaga: $repeatedCharsjest tablicą. Domyślnie Powershell łączy elementy tablicy za pomocą spacji podczas konwertowania tablicy na ciąg. Zatem wyrażenie regularne zawiera spacje (w tym przykładzie [^l o]). Odstępy nie wpływają na wynik, ponieważ ciąg wejściowy zawiera tylko litery.

mazzy
źródło
1

APL (Dyalog Extended) , 8 bajtów SBCS

Anonimowa ukryta funkcja prefiksu.

∊⊢⊆⍨1<⍧⍨

Wypróbuj online!

⍧⍨ odliczanie selfie (policz wystąpienia elementów argumentu w samym argumencie)

1< Maska boolowska, w której jeden jest mniejszy

⊢⊆⍨ podziel argument za pomocą tej maski (rozpoczęcie nowej partycji na 1s i usunięcie na 0s)

ε nlist (spłaszczyć)

Adám
źródło
1

JavaScript, 45 bajtów

s=>[...s].filter(c=>s.match(c+'.*'+c)).join``
kamoroso94
źródło
1

R , 70 bajtów

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

Wypróbuj online!

Słaba próba, nawet z 20 najlepszych języków TIOBE. Wiem, że coś można zrobić w drugiej połowie, ale w tej chwili wszelkie golfy mi uciekają.

Sumner18
źródło
1

JavaScript, 34 bajty

Dane wejściowe jako ciąg znaków, dane wyjściowe jako tablica znaków.

s=>[...s].filter(x=>s.split(x)[2])

Wypróbuj online!

Kudłaty
źródło
Ładny. Oto alternatywny 34-bajtowy przy użyciu map: tio.run
Oliver
@Oliver, niezupełnie .
Kudłaty
0

PHP - 137

Kod

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

Normalny kod

$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
źródło
0

PHP - 83 78

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

Poprawiona wersja:

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

Oczywiście wymaga to wyłączenia powiadomień

Edycja: Ulepszenie inspirowane przez @hengky mulyono

Jestem taki zły w codegolf :)

milo5b
źródło
0

C ++, 139 bajtów

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;

bez golfa:

#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
źródło