Dołącz i usuń


14

Biorąc pod uwagę jedną linię, która składa się tylko z liter, wykonaj następujące czynności:

  • Utrzymujesz ciąg pusty na początku.
  • Jeśli następny ciąg wejściowy znajduje się w ciągu, usuń go z ciągu.
  • Jeśli następnego znaku wejściowego nie ma w ciągu, dołącz go do ciągu.

Wyprowadza końcowy stan ciągu.

Możesz bezpiecznie założyć, że dane wejściowe zawierają co najmniej jeden znak (tzn. Niepuste), ale nie ma gwarancji, że dane wyjściowe nie są puste.

Pseudokod (zachęcamy do gry w golfa):

str = EMPTY
for each character ch in input
  if ch exists in str
    remove all ch from str
  else
    append ch to str
print str

Dane wejściowe pasują do wyrażenia regularnego ^[A-Za-z]+$.

Przykładowe przypadki testowe:

ABCDBCCBE -> ADCBE
ABCXYZCABXAYZ -> A
aAABBbAbbB -> aAbB
GG -> (empty)

Dane wejściowe można podać w dowolny odpowiedni sposób, ale należy je traktować jako ciąg znaków i to samo dla danych wyjściowych. Program nie powinien wychodzić z błędem.

Zwycięża najkrótszy program w każdym języku!

Dodatkowe (opcjonalne): wyjaśnij, jak działa Twój program. Dziękuję Ci.


Czy linia może być pusta?
user202729,

1
@ user202729 Nie. Zmieniłem trochę (nie unieważnia żadnej odpowiedzi), więc dane wejściowe nigdy nie są puste.
iBug

1
Dlaczego więc odrzuciłeś sugestię edycji ais523 (link) ?
user202729,

Odpowiedzi:


10

Haskell , 44 42 bajty

foldl(#)""
s#x|z<-filter(/=x)s=z++[x|z==s]

Wypróbuj online! Edycja: -2 bajty dzięki Zgarb!

Wyjaśnienie:

Druga linia definiuje funkcję, (#)która pobiera ciąg znaków si znak xi wykonuje operację usuwania lub dołączania. Osiąga się to przez filterwygaszenie każdego wystąpienia xin s, co powoduje powstanie ciągu z. Jeśli xnie występuje w s, to zjest równe si z++[x|z==s]zwraca oryginalny ciąg z xdołączonym. W przeciwnym razie [x|z==s]zwraca pusty ciąg i zwracany jest tylko ciąg filtrowany.

foldl(#)""jest anonimową funkcją, która pobiera ciąg znaków i dodaje jeden znak po drugim początkowo pusty ciąg ""z funkcją (#).


2
42 bajty przez ponowne użycie filtra.
Zgarb


8

J , 21 19 bajtów

#~~:&.|.(2|*)1#.=/~

Jak to działa:

=/~ - tworzy tabelę równości znaków w ciągu:

   a =. 'ABCXYZCABXAYZ'
   ]b =: =/~ a 
1 0 0 0 0 0 0 1 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0 0 0 0
0 0 1 0 0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0 0 0 1
0 0 1 0 0 0 1 0 0 0 0 0 0
1 0 0 0 0 0 0 1 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 1 0 0 0
1 0 0 0 0 0 0 1 0 0 1 0 0
0 0 0 0 1 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0 0 0 1

1#. - suma każdego wiersza według przelicznika podstawowego 1 (ile razy litera występuje)

   ]c =: 1#. b
3 2 2 2 2 2 2 3 2 2 3 2 2

~:&.|- odwróć, następnie zastosuj sito nub (unikalny jest char) i odwróć ponownie. W ten sposób znajduję ostatnie wystąpienia znaków w ciągu:

   ]d =. ~:&.|. a
0 0 0 0 0 0 1 0 1 1 1 1 1

* - mnoży liczbę przez 1 dla ostatniej pozycji znaku w sringu, przez 0 w przeciwnym razie, obliczoną przez powyższe ~:&.|

   ]e =. c * d
0 0 0 0 0 0 2 0 2 2 3 2 2

2| - moduł 2 (ustawia na 0 pozycje znaków, które się liczą):

   ]f =. 2| e 
0 0 0 0 0 0 0 0 0 0 1 0 0

#~- skopiuj prawy argument left arg. razy (~ odwraca miejsca argumentów)

]f # a A

Wypróbuj online!


6

Brainfuck, 95 bajtów

,[<<<[[->+>>>+<<<<]>>>[-<+<->>]<<[[-]<]>[[-]>>[-]>[[-<+>]>]<<[<]<<]<<]<[->>>>[-]<<<]>>>>[->+<]>>[>]>>,]<<<[.<]

Wypróbuj online

Jak to działa

, Gets first input
[ Starts loop
    <<< Go to start of string
    [ Loop over the string
        [->+>>>+<<<<] Duplicates the current char of the string
        >>>[-<+<->>] Duplicates and subtracts the inputted char from the duplicate of the string char
        <<[[-]<] If the char is different to the input, remove the difference
        > If the char is the same
        [
            [-]>>[-]>[[-<+>]>]<<[<]<< Remove the char from the string and sets the inputted char to 0
        ]
        << Moves to the next char of the string
    ]
    >>>[->+<] adds the inputted char to the string
    >>[>]>>, gets the next input
]
<<<[.<] prints the string



2

R , 92 84 77 bajtów

for(i in el(strsplit(scan(,y<-''),y)))y=c(y[y!=i],if(!i%in%y)i);cat(y,sep='')

Wypróbuj online!

-15 bajtów dzięki djhurio

Wyjaśnienie

djhurio zapewnił doskonałą odpowiedź R, unikając forpętli - jak programiści R instynktownie robią z reguły (łącznie ze mną). Oto odpowiedź R, która wykorzystuje forpętlę (i zapisuje kilka bajtów w procesie).

  • x=scan(,''); - przypisz dane wejściowe do zmiennej x
  • y=''; - utwórz pusty ciąg w zmiennej o nazwie y
  • for(i in el(strsplit(x,'')))- dla każdej postaci iwx
  • y=c(y[y!=i],if(!i%in%y)i)- przypisać do ykażdego elementu, yktóry nie jest równy i, dołączając, ijeśli jeszcze igo nie byłoy
  • cat(y,sep='')- wydrukuj elementy ybez odstępu między nimi

Uwaga

Jeśli klikniesz powyższy link TIO, znajdziesz w nagłówku library(methods); ma to na celu rozwiązanie błędu djhurio występującego w związku z el()funkcją - funkcja jest dostarczana przez methodspakiet, który w dowolnej wersji R, z której korzystałem, jest domyślnie ładowany, ale z jakiegokolwiek powodu nie jest to TIO. Jeśli library(methods)zostanie usunięty z nagłówka i unlistzastąpiony el, zyskuję cztery bajty, ale tak też zrobi djhurio , ustawiając liczbę naszych bajtów odpowiednio na 96 88 i 99.


Niezłe. Nigdy nie myślałem, że pętla będzie krótsza. Możesz go jeszcze skrócić, pomijając instrukcję else for(i in el(strsplit(scan(,y<-''),y)))y=c(y[y!=i],if(!i%in%y)i);cat(y,sep='').
djhurio

@ djhurio - Wiem, prawie nigdy nie jest tak, że w R a for loop pomoże w czymkolwiek. Jeśli chodzi o twoją sugestię: świetny pomysł! Sugestia została uwzględniona w odpowiedzi.
duckmayr

1
@djhurio - wystarczy; Byłem zbyt zajęty patrzeniem na różnicę wprowadzoną przez pominięcie oświadczenia else. Nie widziałem, jak zmieniłeś początek. Edycja teraz. Świetna robota!
duckmayr

1
@djhurio @duckmayr istnieje 73-bajtowe rozwiązanie, które zasadniczo bierze to rozwiązanie i stosuje nieco inne podejście do wydobywania znaków. Tak naprawdę nie miałem ochoty publikować tego jako osobnej odpowiedzi. Należy również pamiętać, że ...[[1]]jest dłuższy niż, el(...)ale krótszy niż unlist(...), pod warunkiem, że ...jest to lista długości 1.
Giuseppe,

1
podrap to, znalazłem 70-bajkową odpowiedź, ponieważ 0jest to nulznak i zostaje przekonwertowany na pusty ciąg.
Giuseppe,

2

MATL , 6 bajtów

vi"@X~

Nie działa w środowisku TIO, ale działa dobrze w implementacji MATLAB, a dzięki nowej łatce możesz wypróbować ją w MATL Online

X~jest równa setxorlub różnica symetryczna, co robi dokładnie to, o co prosi wyzwanie. Reszta po prostu zapętla dane wejściowe i"@i zaczyna od pustego łańcucha, łącząc cały stos, który jest pusty na początku (dzięki Luis Mendo).



1

JavaScript (ES6), 60 bajtów

s=>[...s].map(c=>s=s.match(c)?s.split(c).join``:s+c,s='')&&s

Przypadki testowe


Przesłałem odpowiedź Retina @ MartinEndera i miała ona tylko 45 bajtów ...
Neil,


1

APL + WIN, 19 bajtów

Logika podobna do rozwiązania J Galena.

(2|+⌿⌽<\⌽c∘.=c)/c←⎕     

1

Wolfram Language (Mathematica) , 36 bajtów

#//.{a___,x_,b___,x_,c___}:>{a,b,c}&

Wypróbuj online!

Pobiera dane wejściowe i wyjściowe jako listę znaków.

Jak to działa

Używa //.(aliasu ReplaceRepeated), aby znaleźć dwa powtarzające się znaki i usunąć oba, dopóki nie będzie już więcej powtarzających się znaków. Jeśli postać występuje więcej niż dwa razy, Mathematica zawsze usunie pierwsze dwa wystąpienia. Jeśli więc postać pojawi się nieparzystą liczbę razy, jej ostatnią instancją zawsze będzie ta, która przeżyje.


1

Prolog 81 bajtów

a([],O,O).
a([I|J],K,O):-delete(K,I,F),(K=F->append(K,[I],M),a(J,M,O);a(J,F,O)).

Wersja nie zaciemniona:

append_and_eraze([], Output, Output).
append_and_eraze([I | Input], Interim, Output) :-
    delete(Interim, I, Filtered),
    ( Interim = Filtered ->
      append(Interim, [I], Interim1),
      append_and_eraze(Input, Interim1, Output)
    ;
    append_and_eraze(Input, Filtered, Output)
    ).
  1. delete/3 zapewnia, że ​​jego trzeci argument ujednolica się z pierwszym argumentem, a wszystkie wystąpienia drugiego argumentu zostaną z niego usunięte.
  2. Jeśli okażą się takie same, dodajemy element (nie został usunięty).
  3. append/3 jak sama nazwa dołącza element do listy.
  4. Powtarzamy na elementach wejściowych, aż trafimy na [](pustą listę), w którym to momencie wynik pośredni zostanie zjednoczony z pożądanym wynikiem.

Test:

?- append_and_eraze(`ABCDBCCBE`, [], X), string_codes(Y, X).
X = [65, 68, 67, 66, 69],
Y = "ADCBE".

?- append_and_eraze(`ABCXYZCABXAYZ`, [], X), string_codes(Y, X).
X = [65],
Y = "A".

?- append_and_eraze(`aAABBbAbbB`, [], X), string_codes(Y, X).
X = [97, 65, 98, 66],
Y = "aAbB".

?- append_and_eraze(`GG`, [], X), string_codes(Y, X).
X = [],
Y = "".

Niektóre Prologi traktują ciągi w podwójnych cudzysłowach jak listy, SWI można skonfigurować tak, aby robił to samo, ale dla uproszczenia string_codes/2ładnie sformatowałem dane wyjściowe.



1

R , 84 bajtów

y=el(strsplit(scan(,""),""));cat(unique(y[colSums(outer(y,y,"=="))%%2>0],,T),sep="")

Wypróbuj online!

Inne rozwiązanie, ale tutaj są lepsze odpowiedzi R.

R , 88 bajtów

z=table(y<-el(strsplit(scan(,""),"")));cat(setdiff(unique(y,,T),names(z[!z%%2])),sep="")

Wypróbuj online!

Dzięki Giuseppe za -7 bajtów!

Odpowiedź kaczki jest krótsza .

  1. scan(,"") odczytać wejście ze standardowego wejścia.
  2. y<-el(strsplit(scan(,""),""))podziel wprowadzanie na znaki i zapisz jako y.
  3. z=table(y<-el(strsplit(scan(,""),"")))oblicz częstotliwości każdego znaku i zapisz wynikową tabelę jako z;
  4. unique(y,,T) zabierz unikalne postacie z prawej strony.
  5. names(z[!z%%2]) wybierz tylko parzyste liczby i wyodrębnij nazwy.
  6. setdiff(unique(y,,T),names(z[!z%%2])) usuń postacie z parzystą liczbą.
  7. cat(setdiff(unique(y,,T),names(z[!z%%2])),sep="") wydrukować wynik.

Przyczyną twojego błędu jest to, że el()pochodzi on z methodspakietu, który choć zwykle ładowany jest domyślnie, nie jest TIO (omówiony w mojej odpowiedzi poniżej)
duckmayr

dlaczego używasz rev(unique(rev(y)))? Czy po prostu nie unique(y)zadziała? ooohhh czekaj, rozumiem, chcesz unikalne postacie od prawej do lewej. W takim przypadku unique(y,,T)(ustawienie fromLast=T) wyniesie 88 bajtów .
Giuseppe,

0

Alice , 9 bajtów

/X&@
\io/

Wypróbuj online!

Wyjaśnienie

Zasadniczo port odpowiedzi Erika . Poza odrobiną przekierowania adresu IP kod jest po prostu:

i&Xo@

co robi:

i   Read all input.
&X  Fold symmetric multiset difference over the input.
o   Output the result.
@   Terminate.



0

Rubin , 53 bajty

->s{s.reverse.uniq.select{|c|s.count(c)%2>0}.reverse}

Wypróbuj online!

Dane wejściowe i wyjściowe są tablicą znaków. Testuj połączenia kodowe .charsi .joindla wygody.

Wyjaśnienie

Wykorzystuje fakt, że litery w wynikowym ciągu pojawiają się nieparzystą liczbę razy i w kolejności od prawej do lewej.

->s{                # lambda function taking char-array argument
    s.reverse           # reverse the input
    .uniq               # get unique characters
    .select{|c|         # select only those which...
        s.count(c)%2>0      # appear in the input array an odd number of times
    }.reverse           # reverse back and return
}

0

Pyth, 13 bajtów

{_xD_Qf%/QT2Q

Pobiera dane wejściowe jako listę znaków. Przetestuj to!

      f     Q            (f)ilter input (Q)
        /QT              On how many times (/) each character (T) appears in the 
                           input (Q)
       %   2             Only allow odd numbers of occurences (when x % 2 = 1)
 _xD_Q                   Sort (D) descending (the first _) by the location (x) of 
                           the last (the second _) inde(x) of the target character
                           in the input (Q)
{                        Remove duplicates

0

Röda , 34 bajty

{a=[]a-=_ if[_1 in a]else a+=_1;a}

Wypróbuj online!

To jest bezpośrednie tłumaczenie pseudokodu. Traktuje dane wejściowe i wyjściowe jako strumienie znaków.

Wyjaśnienie:

{                    /* Anonymous function                   */
    a=[]             /* initialize a                         */
                     /* For each character _1 in the stream: */
    a-=_ if[_1 in a] /*  Remove it from a if a contains it   */
    else a+=_1;      /*  Otherwise append it to a            */
    a                /* Push characters in a to the stream   */
}

0

Python 3 , 73 bajty

Nie najkrótszy, ale podoba mi się to podejście.

lambda s:''.join(c*(s.count(c)%2)*(i==s.rfind(c))for i,c in enumerate(s))

Wypróbuj online!

Pętle przechodzą przez ciąg, zachowując tylko te znaki, w których:

  • (s.count(c)%2) == 0 - Postać pojawia się parzysta liczba razy.
  • (i==s.rfind(c)) - Obecny indeks jest ostatnim pojawieniem się danej postaci.

0

REXX , 102 bajty

a=arg(1)
s=''
do while a>''
  b=right(a,1)
  if countstr(b,a)//2 then s=b||s
  a=changestr(b,a,'')
  end
say s

Wypróbuj online!

Jak to działa: weź prawą literę, zobacz, czy liczba wystąpień jest parzysta czy nieparzysta (która również podwaja się jako wartość prawdy), a jeśli nieparzysta, dodaj ją do ciągu wyjściowego. Następnie usuń wszystkie wystąpienia litery z ciągu wejściowego. Powtarzaj do momentu wyczerpania się danych wejściowych.



0

Java 8, 93 bytes

A lambda from String to String. Just an implementation of the pseudocode in the question.

s->{String o="";for(char c:s.toCharArray())o=o.indexOf(c)<0?o+c:o.replace(c+"","");return o;}

Try It Online

Java 8, 182 bytes

Here's another lambda of the same type that uses streams! It's probably more efficient.

s->s.join("",s.chars().mapToObj(c->(char)c+"").filter(c->s.replaceAll("[^"+c+"]","").length()%2>0).distinct().sorted((c,d)->s.lastIndexOf(c)-s.lastIndexOf(d)).toArray(String[]::new))

Try It Online

Ungolfed

s ->
    s.join(
        "",
        s.chars()
            .mapToObj(c -> (char) c + "")
            .filter(c -> s.replaceAll("[^" + c + "]", "").length() % 2 < 0)
            .distinct()
            .sorted((c, d) -> s.lastIndexOf(c) - s.lastIndexOf(d))
            .toArray(String[]::new)
    )

0

R, 70 bytes

function(s){for(i in utf8ToInt(s))F=c(F[F!=i],i*!i%in%F);intToUtf8(F)}

Try it online!

I was encouraged by djhurio to post this solution; djhurio's answer can be found here.

This uses the same idea as duckmayr's answer, but it leverages a numeric approach by converting the string to its codepoints rather than splitting it into characters, and is a function rather than a full program so it can return the new string rather than printing to stdout.

function(s) {
 for(i in utf8ToInt(s))           # convert string to codepoints and iterate over it
  F=c(F[F!=i],                    # remove duplicates and append
      i*!i%in%F)                  # 0 if in F, i otherwise
 intToUtf8(F)                     # collapse from codepoints to string
}

One important observation is that F is initialized to FALSE or 0 and utf8ToInt(0)=="", so this will succeed for the empty string as well as correctly collapsing the codepoints.


0

PHP, 71+1 bytes

while(~$c=$argn[$i++])$s=strstr($s,$c)?strtr($s,[$c=>""]):$s.$c;echo$s;

Run as pipe with -nR or try it online.



0

SNOBOL4 (CSNOBOL4), 97 95 bytes

	S =INPUT
N	S LEN(1) . C REM . S :F(O)
	O C :S(R)
	O =O C :(N)
R	O C =:S(R)F(N)
O	OUTPUT =O
END

Try it online!

	S =INPUT			;* read input
N	S LEN(1) . C REM . S :F(O)	;* take the first character of S and assign it to C,
					;* assign the remainder to S, and if S has no characters left, goto O
	O C :S(R)			;* if C matches anything in O, goto R, otherwise go to next line
	O =O C :(N)			;* append C to O and goto N
R	O C =:S(R)F(N)			;* as long as C matches O, replace it with ''
					;* (unassigned variables default to the null string)
					;* then goto N once it fails to match
O	OUTPUT =O			;* output the string
END					;* terminate the program
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.