Aggiungi e cancella


14

Data una riga che consiste solo di lettere, elaborare come segue:

  • Mantieni una stringa vuota all'inizio.
  • Se il carattere di input successivo è nella stringa, rimuoverlo dalla stringa.
  • Se il carattere di input successivo non è nella stringa, aggiungilo alla stringa.

Emette lo stato finale della stringa.

Puoi tranquillamente supporre che l'input sia composto da almeno un carattere (cioè non vuoto), ma non c'è garanzia che l'output non sia vuoto.

Pseudocodice (sentiti libero di giocare a golf):

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

L'input corrisponde all'espressione regolare ^[A-Za-z]+$.

Esempi di casi di test:

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

L'input può essere dato in qualsiasi modo applicabile, ma deve essere trattato come una stringa e lo stesso per l'output. Il programma non dovrebbe uscire con un errore.

Vince il programma più corto in ogni lingua!

Extra (opzionale): spiega come funziona il tuo programma. Grazie.


La riga può essere vuota?
user202729

1
@ user202729 No. Ho cambiato un po '(non invalida alcuna risposta) quindi l'ingresso non è mai vuoto.
iBug,

1
Quindi perché hai rifiutato il suggerimento di modifica di ais523 (link) ?
user202729,

Risposte:


10

Haskell , 44 42 byte

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

Provalo online! Modifica: -2 byte grazie a Zgarb!

Spiegazione:

La seconda riga definisce una funzione (#)che accetta una stringa se un carattere xed esegue la rimozione o l'aggiunta. Ciò si ottiene filtering fuori ogni occorrenza di xa s, risulta della stringa z. Se xnon si verifica in s, allora zè uguale se z++[x|z==s]restituisce la stringa originale con l' xaggiunta. Altrimenti [x|z==s]restituisce la stringa vuota e viene restituita solo la stringa filtrata.

foldl(#)""è una funzione anonima che accetta una stringa e aggiunge un carattere dopo l'altro la stringa inizialmente vuota ""con la funzione (#).


2
42 byte riutilizzando il filtro.
Zgarb,


8

J , 21 19 byte

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

Come funziona:

=/~ - crea una tabella di uguaglianza dei caratteri nella stringa:

   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#. - somma di ogni riga per conversione di base 1 (quante volte compare la lettera)

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

~:&.|- invertire, quindi applicare nub setaccio (è il carattere univoco) e invertire nuovamente. Quindi trovo le ultime occorrenze dei caratteri nella stringa:

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

* - moltiplica il conteggio per 1 per l'ultima posizione del personaggio nell'incrocio, per 0 altrimenti, calcolato da quanto sopra ~:&.|

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

2| - modulo 2 (imposta a 0 le posizioni dei caratteri che hanno un conteggio pari):

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

#~- copia l'argomento giusto left arg. volte (~ inverte i luoghi degli arg)

]f # a A

Provalo online!


6

Brainfuck, 95 byte

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

Provalo online

Come funziona

, 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 byte

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

Provalo online!

-15 byte grazie a djhurio

Spiegazione

djhurio ha fornito un'eccellente risposta R evitando un forloop - poiché i programmatori R fanno istintivamente una regola (me compreso). Ecco una risposta R che utilizza un forciclo (e salva alcuni byte nel processo).

  • x=scan(,''); - assegna l'ingresso alla variabile x
  • y=''; - crea una stringa vuota in una variabile chiamata y
  • for(i in el(strsplit(x,'')))- per ogni personaggio iinx
  • y=c(y[y!=i],if(!i%in%y)i)- assegnare a yogni elemento ynon uguale a i, aggiungendo ise inon era già iny
  • cat(y,sep='')- stampa gli elementi di ysenza spazio tra loro

Nota

Se fai clic sul link TIO sopra, troverai nell'intestazione library(methods); questo per far fronte all'errore djhurio riscontrato sulla el()funzione - la funzione è fornita dal methodspacchetto, che in qualsiasi versione di R che ho usato, è caricata di default, ma per qualsiasi motivo non è di TIO. Se library(methods)viene rimosso dall'intestazione e unlistviene sostituito el, guadagno quattro byte, ma lo farebbe anche djhurio , mettendo il numero dei nostri byte rispettivamente a 96 88 e 99.


Ben fatto. Non avrei mai pensato che il loop fosse più breve. Puoi renderlo ancora più breve omettendo la dichiarazione else for(i in el(strsplit(scan(,y<-''),y)))y=c(y[y!=i],if(!i%in%y)i);cat(y,sep='').
djhurio,

@djhurio - Lo so, non è quasi mai il caso che in R a for loop possa aiutare con qualsiasi cosa. Per quanto riguarda il tuo suggerimento: ottima idea! Il suggerimento è ora incorporato nella risposta.
duckmayr,

1
@djhurio: abbastanza giusto; Ero troppo occupato a guardare la differenza introdotta dall'omessa dichiarazione else che non vedevo come tu avessi cambiato l'inizio. Modifica ora. Ottimo lavoro!
duckmayr,

1
@djhurio @duckmayr esiste una soluzione a 73 byte che sta fondamentalmente prendendo questa soluzione e usando un approccio leggermente diverso per estrarre i caratteri. Non avevo proprio voglia di pubblicarlo come risposta separata. Si noti inoltre che ...[[1]]è più lungo el(...)ma più breve di unlist(...), a condizione che ...sia un elenco di lunghezza 1.
Giuseppe,

1
graffio, ho trovato una risposta di 70 ciao poiché 0è il nulpersonaggio e viene convertito nella stringa vuota.
Giuseppe,

2

MATL , 6 byte

vi"@X~

Non funziona nell'ambiente TIO, ma funziona bene sull'implementazione MATLAB e, grazie a una nuova patch, puoi provarlo su MATL Online

X~uguale setxoro differenza simmetrica, che fa esattamente ciò che la sfida chiede. Il resto è semplicemente in loop sull'input i"@e inizia con una stringa vuota concatenando l'intero stack che è vuoto all'inizio (grazie Luis Mendo).



1

JavaScript (ES6), 60 byte

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

Casi test


Ho portato la risposta Retina di MartinEnder ed era solo 45 byte ...
Neil


1

APL + WIN, 19 byte

Logica simile alla soluzione J di Galeno.

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

1

Wolfram Language (Mathematica) , 36 byte

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

Provalo online!

Accetta input e output come un elenco di caratteri.

Come funziona

Utilizza //.(alias ReplaceRepeated) per trovare due caratteri ripetuti ed eliminarli entrambi, fino a quando non esistono più caratteri ripetuti. Se il personaggio si presenta più di due volte, Mathematica eliminerà sempre le prime due occorrenze. Quindi, se un personaggio si presenta un numero dispari di volte, la sua ultima istanza sarà sempre quella per sopravvivere.


1

Prolog 81 byte

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

Versione non offuscata:

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 assicura che il suo terzo argomento si unisca al suo primo argomento, rimuovendo tutte le istanze del secondo argomento.
  2. Se quelli risultano essere gli stessi, aggiungiamo l'elemento (non è stato rimosso).
  3. append/3 secondo il suo nome, aggiunge un elemento all'elenco.
  4. Ricorriamo sugli elementi dell'input fino a quando non premiamo [](elenco vuoto), a quel punto il risultato intermedio si unificherà con il risultato desiderato.

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 = "".

Alcuni Prolog trattano le stringhe tra virgolette come liste, SWI può essere configurato per fare lo stesso, ma per semplicità, ho usato string_codes/2per formattare l'output in modo corretto.



1

R , 84 byte

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

Provalo online!

Un'altra soluzione, ma ci sono R migliori risposte qui.

R , 88 byte

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

Provalo online!

Grazie a Giuseppe per -7 byte!

C'è una risposta più breve di duckmayr .

  1. scan(,"") leggere input da stdin.
  2. y<-el(strsplit(scan(,""),""))dividere l'input per caratteri e salvare come y.
  3. z=table(y<-el(strsplit(scan(,""),"")))calcolare le frequenze di ciascun carattere e salvare la tabella risultante come z;
  4. unique(y,,T) prendi personaggi unici dal lato destro.
  5. names(z[!z%%2]) seleziona solo conteggi pari ed estrai i nomi.
  6. setdiff(unique(y,,T),names(z[!z%%2])) rimuovere i personaggi con un numero pari.
  7. cat(setdiff(unique(y,,T),names(z[!z%%2])),sep="") stampa l'output.

Il motivo del tuo errore è che el()proviene dal methodspacchetto, che mentre in genere caricato per impostazione predefinita, non è di TIO (discusso nella mia risposta di seguito)
duckmayr

perché stai usando rev(unique(rev(y)))? Non unique(y)funzionerebbe? ooohhh aspetta vedo, vuoi i personaggi unici da destra a sinistra. In tal caso unique(y,,T)(impostazione fromLast=T) saranno 88 byte .
Giuseppe,

0

Alice , 9 byte

/X&@
\io/

Provalo online!

Spiegazione

Fondamentalmente un porto della risposta di Erik . A parte un po 'di reindirizzamento IP, il codice è davvero solo:

i&Xo@

che fa:

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



0

Rubino , 53 byte

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

Provalo online!

Input e output sono entrambi una matrice di caratteri. Chiamate di codice di prova .charse .joinper comodità.

Spiegazione

Usa il fatto che le lettere nella stringa risultante appaiono un numero dispari di volte e nell'ordine da destra a sinistra.

->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 byte

{_xD_Qf%/QT2Q

Accetta input come elenco di caratteri. Provalo!

      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 byte

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

Provalo online!

Questa è una traduzione diretta dello pseudocodice. Tratta l'input e l'output come flussi di caratteri.

Spiegazione:

{                    /* 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 byte

Non il più breve, ma mi piace questo approccio.

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

Provalo online!

Passa attraverso la stringa, mantenendo solo quei caratteri in cui:

  • (s.count(c)%2) == 0 - Il personaggio appare un numero pari di volte.
  • (i==s.rfind(c)) - L'indice corrente è l'ultima apparizione del personaggio in questione.

0

REXX , 102 byte

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

Provalo online!

Come funziona: prendi la lettera più a destra, controlla se il numero di occorrenze è pari o dispari (che funge anche da valore di verità) e, se dispari, aggiungilo alla stringa di output. Quindi rimuovere tutte le occorrenze della lettera dalla stringa di input. Ripetere fino a quando l'input è esaurito.



0

Java 8, 93 byte

Un lambda da Stringa String. Solo un'implementazione dello pseudocodice nella domanda.

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

Provalo online

Java 8, 182 byte

Ecco un'altra lambda dello stesso tipo che utilizza stream! Probabilmente è più efficiente.

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

Provalo 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 byte

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

Provalo online!

Sono stato incoraggiato da djhurio a pubblicare questa soluzione; La risposta di djhurio può essere trovata qui .

Questo utilizza la stessa idea della risposta di duckmayr , ma sfrutta un approccio numerico convertendo la stringa in punti di codice piuttosto che dividerla in caratteri, ed è una funzione piuttosto che un programma completo in modo da poter restituire la nuova stringa anziché stampare su 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
}

Un'osservazione importante è che Fviene inizializzato a FALSEo 0e utf8ToInt(0)=="", quindi questo avrà successo per la stringa vuota così collasso come correttamente codepoints.


0

PHP, 71 + 1 byte

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

Esegui come pipe -nRo provalo online .



0

SNOBOL4 (CSNOBOL4) , 97 95 byte

	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

Provalo 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
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.