Agregar y borrar

14

Dada una línea que consta de solo letras, procese de la siguiente manera:

  • Mantiene una cadena que está vacía al principio.
  • Si el siguiente carácter de entrada está en la cadena, elimínelo de la cadena.
  • Si el siguiente carácter de entrada no está en la cadena, agréguelo a la cadena.

Salida del estado final de la cadena.

Puede suponer con seguridad que la entrada consta de al menos un carácter (es decir, no vacío), pero no hay garantía de que la salida no esté vacía.

Pseudocódigo (siéntase libre de jugar al 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

La entrada coincide con la expresión regular ^[A-Za-z]+$.

Ejemplos de casos de prueba:

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

La entrada se puede dar de cualquier manera aplicable, pero debe tratarse como una cadena, y lo mismo para la salida. El programa no debe salir con un error.

¡El programa más corto en cada idioma gana!

Extra (Opcional): explique cómo funciona su programa. Gracias.

iBug
fuente
¿Puede la línea estar vacía?
usuario202729
1
@ user202729 No. Cambié un poco (no invalida ninguna respuesta) para que la entrada nunca esté vacía.
iBug
1
Entonces, ¿por qué rechazaste la sugerencia de edición de ais523 (enlace) ?
user202729

Respuestas:

10

Haskell , 44 42 bytes

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

Pruébalo en línea! Editar: -2 bytes gracias a Zgarb!

Explicación:

La segunda línea define una función (#)que toma una cadena sy un carácter xy realiza la eliminación o la adición. Esto se logra filtereliminando cada aparición de xin s, dando como resultado la cadena z. Si xno ocurre en s, entonces zes igual sy z++[x|z==s]produce la cadena original con xadjunta. De lo contrario, se [x|z==s]obtiene la cadena vacía y solo se devuelve la cadena filtrada.

foldl(#)""es una función anónima que toma una cadena y agrega un carácter después del otro, la cadena inicialmente vacía ""con la función (#).

Laikoni
fuente
2
42 bytes reutilizando el filtro.
Zgarb
9

Jalea , 3 bytes

œ^/

Pruébalo en línea!

Programa completo

Erik el Outgolfer
fuente
¿Por qué œ^/no es suficiente?
Jonathan Allan
@JonathanAllan El programa no debe salir con un error.
Erik the Outgolfer
the input is never emptyBueno, ahora funciona.
usuario202729
8

J , 21 19 bytes

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

Cómo funciona:

=/~ - hace una tabla de igualdad de los caracteres en la cadena:

   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 de cada fila por conversión de base 1 (cuántas veces aparece la letra)

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

~:&.|- invierta, luego aplique el tamiz de protuberancia (es el carbón único) e invierta nuevamente Así encuentro las últimas ocurrencias de los caracteres en la cadena:

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

* - multiplica el recuento por 1 para la última posición del personaje en la banda, por 0 de lo contrario, calculado por lo anterior ~:&.|

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

2| - módulo 2 (establece en 0 las posiciones de los caracteres que cuentan incluso):

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

#~- Copie el argumento derecho arg de la izquierda. veces (~ invierte los lugares de los argumentos)

]f # a A

Pruébalo en línea!

Galen Ivanov
fuente
6

Brainfuck, 95 bytes

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

Pruébalo en línea

Cómo funciona

, 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
Jo King
fuente
4

Haskell , 47 bytes

Otro bytes el polvo gracias a Bruce Forte.

import Data.List
foldl1(\x y->union(x\\y)$y\\x)

Pruébalo en línea!

Toma una lista de cadenas.

La diferencia simétrica es molesta ...

totalmente humano
fuente
++ahorra 2 bytes unioncon este método.
Ørjan Johansen
2

R , 92 84 77 bytes

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

Pruébalo en línea!

-15 bytes gracias a djhurio

Explicación

djhurio proporcionó una excelente respuesta R evitando un forbucle, como lo hacen instintivamente los programadores R por regla general (incluido yo mismo). Aquí hay una respuesta R que utiliza un forbucle (y ahorra algunos bytes en el proceso).

  • x=scan(,''); - asignar la entrada a la variable x
  • y=''; - Crear una cadena vacía en una variable llamada y
  • for(i in el(strsplit(x,'')))- por cada personaje ienx
  • y=c(y[y!=i],if(!i%in%y)i)- asignar a ycada elemento de yeso no es igual a i, agregando isi aún ino estaba eny
  • cat(y,sep='')- imprime los elementos ysin espacio entre ellos

Nota

Si hace clic en el enlace TIO anterior, encontrará en el encabezado library(methods); esto es para lidiar con el error que djhurio experimentó con respecto a la el()función: la función es proporcionada por el methodspaquete, que en cualquier versión de R que he usado, se carga por defecto, pero por cualquier razón no es por TIO. Si library(methods)se elimina del encabezado y unlistse sustituye el, gano cuatro bytes, pero también lo haría djhurio , poniendo nuestros recuentos de bytes en 96 88 y 99 respectivamente.

Duckmayr
fuente
Buena esa. Nunca pensé que el ciclo será más corto. Puede hacerlo aún más corto omitiendo la instrucción elsefor(i in el(strsplit(scan(,y<-''),y)))y=c(y[y!=i],if(!i%in%y)i);cat(y,sep='') .
djhurio
@djhurio - Lo sé, casi nunca ocurre que en R a for loop ayude con algo. En cuanto a su sugerencia: ¡Gran idea! La sugerencia ahora está incorporada en la respuesta.
Duckmayr
1
@djhurio - bastante justo; Estaba demasiado ocupado mirando la diferencia introducida al omitir la declaración else, no vi cómo había cambiado el comienzo. Editando ahora. ¡Buen trabajo!
Duckmayr
1
@djhurio @duckmayr hay una solución de 73 bytes que básicamente toma esta solución y utiliza un enfoque ligeramente diferente para extraer caracteres. Realmente no tenía ganas de publicarlo como una respuesta separada. También tenga en cuenta que ...[[1]]es más largo el(...)pero más corto que unlist(...), siempre que... sea ​​una lista de longitud 1.
Giuseppe
1
tachando eso, encontré una respuesta de 70 bye ya que 0es el nulpersonaje y se convierte en la cadena vacía.
Giuseppe
2

MATL , 6 bytes

vi"@X~

No funciona en el entorno TIO, pero funciona bien en la implementación de MATLAB, y gracias a un parche nuevo, puede probarlo en MATL Online

X~igual setxor, o diferencia simétrica, que hace exactamente lo que el desafío pide. El resto es simplemente recorrer la entrada i"@y comenzar con una cadena vacía concatenando toda la pila que está vacía al comienzo (gracias Luis Mendo).

Sanchises
fuente
2

Python 2 , 56 bytes

-2 bytes gracias a xnor. -3 bytes gracias a los ovs.

lambda s:reduce(lambda a,c:a.replace(c,'')+c[c in a:],s)

Pruébalo en línea!

Literalmente solo jugué al pseudocódigo. :PAG

totalmente humano
fuente
1
Guardar 2 bytes: s=(s+c).replace(c,c[c in s:]).
xnor
@xnor Eso es algo de golf básico ejecutado de manera muy inteligente. ¡Gracias!
Totalmente humano el
1
-1 byte :s=s.replace(c,'')+c[c in s:]
ovs
1
56 bytes usando reduce
ovs
1

JavaScript (ES6), 60 bytes

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

Casos de prueba

Arnauld
fuente
Porté la respuesta de Retina de @ MartinEnder y solo costaba 45 bytes ...
Neil
1

q , 38 bytes

""{$[y in x;except;,][x;y]}/
skeevey
fuente
1

APL + WIN, 19 bytes

Lógica similar a la solución J de Galen.

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

Wolfram Language (Mathematica) , 36 bytes

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

Pruébalo en línea!

Toma entrada y salida como una lista de caracteres.

Cómo funciona

Utiliza //.(alias ReplaceRepeated) para buscar dos caracteres repetidos y eliminar ambos, hasta que no existan más caracteres repetidos. Si el personaje aparece más de dos veces, Mathematica siempre eliminará las dos primeras ocurrencias. Entonces, si un personaje aparece un número impar de veces, su última instancia siempre será la que sobreviva.

Misha Lavrov
fuente
1

Prólogo 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)).

Versión no ofuscada:

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 asegura que su tercer argumento se unifique con su primer argumento, con todas las instancias del segundo argumento eliminadas de él.
  2. Si resultan ser los mismos, agregamos el elemento (no se eliminó).
  3. append/3 según su nombre, agrega un elemento a la lista.
  4. Repetimos en los elementos de la entrada hasta que lleguemos a la [](lista vacía), en cuyo punto el resultado intermedio se unificará con el resultado deseado.

Prueba:

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

Algunos Prologs tratan las cadenas entre comillas dobles como listas, SWI se puede configurar para hacer lo mismo, pero por simplicidad, solía string_codes/2formatear muy bien la salida.

wvxvw
fuente
1

R , 84 bytes

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

Pruébalo en línea!

Otra solución, pero hay mejores respuestas R aquí.

R , 88 bytes

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

Pruébalo en línea!

¡Gracias a Giuseppe por -7 bytes!

Hay una respuesta más corta por duckmayr .

  1. scan(,"") leer la entrada de stdin.
  2. y<-el(strsplit(scan(,""),""))dividir la entrada por caracteres y guardar como y.
  3. z=table(y<-el(strsplit(scan(,""),"")))calcular las frecuencias de cada carácter y guardar la tabla resultante como z;
  4. unique(y,,T) tomar personajes únicos del lado derecho.
  5. names(z[!z%%2]) seleccione solo recuentos pares y extraiga nombres.
  6. setdiff(unique(y,,T),names(z[!z%%2])) eliminar personajes con recuento par.
  7. cat(setdiff(unique(y,,T),names(z[!z%%2])),sep="") imprime la salida.
djhurio
fuente
La razón de su error es que el()proviene del methodspaquete, que normalmente mientras se carga por defecto, no es por TIO (discutido en mi respuesta a continuación)
duckmayr
¿Por qué utiliza rev(unique(rev(y)))? ¿No solo unique(y)funcionaría? ooohhh espera ya veo, quieres los personajes únicos de derecha a izquierda. En ese caso unique(y,,T)(configuración fromLast=T) será de 88 bytes .
Giuseppe
0

Alice , 9 bytes

/X&@
\io/

Pruébalo en línea!

Explicación

Básicamente un puerto de la respuesta de Erik . Además de un poco de redirección de IP, el código es realmente justo:

i&Xo@

que hace:

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

APL (Dyalog) , 16 bytes

{(,⍨~∩)/⍣(≢⍵)⊖⍵}

Pruébalo en línea!

Si se permitieran errores, esto habría sido de 9 bytes:

(,⍨~∩)/∘⊖
Erik el Outgolfer
fuente
¿Qué quieres decir con errores?
FrownyFrog
@FrownyFrog La versión de 9 bytes arrojaría un DOMAIN ERRORsi la cadena está vacía, ya (,⍨~∩)que no tiene un elemento de identidad predefinido.
Erik the Outgolfer
0

Ruby , 53 bytes

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

Pruébalo en línea!

La entrada y la salida son un conjunto de caracteres. Prueba de código de llamadas .charsy .joinpara mayor comodidad.

Explicación

Utiliza el hecho de que las letras en la cadena resultante aparecen un número impar de veces y en el orden de derecha a izquierda.

->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
}
Justin Mariner
fuente
0

Pyth, 13 bytes

{_xD_Qf%/QT2Q

Toma entrada como lista de caracteres. ¡Pruébalo!

      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
Steven H.
fuente
0

Röda , 34 bytes

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

Pruébalo en línea!

Esta es una traducción directa del pseudocódigo. Trata la entrada y la salida como secuencias de caracteres.

Explicación:

{                    /* 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   */
}
fergusq
fuente
0

Python 3 , 73 bytes

No es el más corto, pero me gusta este enfoque.

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

Pruébalo en línea!

Recorre la cadena, manteniendo solo aquellos caracteres donde:

  • (s.count(c)%2) == 0 - El personaje aparece un número par de veces.
  • (i==s.rfind(c)) - El índice actual es la última aparición del personaje en cuestión.
FlipTack
fuente
0

REXX , 102 bytes

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

Pruébalo en línea!

Cómo funciona: tome la letra más a la derecha, vea si el número de ocurrencias es par o impar (que también funciona como un valor de verdad) y si es impar, agréguelo a la cadena de salida. Luego, elimine todas las apariciones de la letra de la cadena de entrada. Repita hasta que se agote la entrada.

idrougge
fuente
0

Java 8, 93 bytes

Una lambda de Stringa String. Solo una implementación del pseudocódigo en la pregunta.

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

Pruébalo en línea

Java 8, 182 bytes

¡Aquí hay otra lambda del mismo tipo que usa secuencias! Probablemente sea más eficiente.

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

Pruébalo en línea

Sin golf

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)
    )
Jakob
fuente
0

R , 70 bytes

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

Pruébalo en línea!

Djhurio me animó a publicar esta solución; la respuesta de djhurio se puede encontrar aquí .

Utiliza la misma idea que la respuesta de duckmayr , pero aprovecha un enfoque numérico al convertir la cadena en sus puntos de código en lugar de dividirla en caracteres, y es una función en lugar de un programa completo para que pueda devolver la nueva cadena en lugar de imprimirla en 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
}

Una observación importante es que Fse inicializa a FALSEo 0y utf8ToInt(0)=="", por lo que este tendrá éxito para la cadena vacía, así como el colapso de los puntos de código correctamente.

Giuseppe
fuente
0

PHP, 71 + 1 bytes

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

Ejecutar como tubería -nRo probarlo en línea .

Titus
fuente
0

Python 3.6 , 69 bytes

lambda a:"".join({c:1 for c in a[::-1] if a.count(c)%2}.keys())[::-1]

Pruébalo en línea!

El orden de inserción de Dict se conserva en Python 3.6.

usuario285259
fuente
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

Pruébalo en línea!

	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
Giuseppe
fuente