Contraer duplicados adyacentes

22

Reto

Dada una lista de enteros, devuelva la lista de estos enteros después de eliminar repetidamente todos los pares de elementos iguales adyacentes.

Tenga en cuenta que si tiene una serie de números iguales de longitud impar, uno de ellos permanecerá y no formará parte de un par.

Ejemplo:

[0, 0, 0, 1, 2, 4, 4, 2, 1, 1, 0]

En primer lugar, se debe eliminar 0, 0, 4, 4y 1, 1para obtener:

[0, 1, 2, 2, 0]

Ahora, debes eliminar 2, 2:

[0, 1, 0]

Y este es el resultado final.

Casos de prueba

[] -> []
[1] -> [1]
[1, 1] -> []
[1, 2] -> [1, 2]
[11, 11, 11] -> [11]
[1, 22, 1] -> [1, 22, 1]
[-31, 46, -31, 46] -> [-31, 46, -31, 46]
[1, 0, 0, 1] -> []
[5, 3, 10, 10, 5] -> [5, 3, 5]
[5, 3, 3, 3, 5] -> [5, 3, 5]
[0, -2, 4, 4, -2, 0] -> []
[0, 2, -14, -14, 2, 0, -1] -> [-1]
[0, 0, 0, 1, 2, 4, 4, 2, 1, 1, 0] -> [0, 1, 0]
[3, 5, 4, 4, 8, 26, 26, 8, 5] -> [3]
[-89, 89, -87, -8, 8, 88] -> [-89, 89, -87, -8, 8, 88]

Tanteo

Este es el , por lo que gana la respuesta más corta en cada idioma.

musicman523
fuente
Sandbox para aquellos que pueden ver publicaciones eliminadas
musicman523
No importa, todos son iguales. El significado de esta frase es que se [14, 14, 14]derrumba a[14]
musicman523
Leí mal el desafío, lo siento. Creía que había que eliminar todos los pares de números cada vez mayores de 1 ( 1,2, 11,12, etc.)
Stephen
¿Podemos tomar la entrada como una cadena delimitada?
Shaggy
2
¿Podría agregar un caso de prueba como -89,89,-87,-8,-88? Tanto mi solución de Japt (sin publicar) como la solución de Retina de Fry fallan allí, produciéndose --87,8.
Shaggy

Respuestas:

5

Jalea , 10 bytes

Œgœ^/€FµÐL

Pruébalo en línea!

Cómo funciona

Œgœ^/€FµÐL  Main link. Argument: A (array)

       µ    Combine all links to the left into a chain.
Œg              Group all adjacent equal items.
    /€          Reduce each group by...
  œ^                symmetric multiset difference.
                In each step, this maps ([], n) to [n] and ([n], n) to [], so the
                group is left with a single item if its length is odd, and no items
                at all if its length if even.
      F         Flatten the resulting array of singleton and empty arrays.
        ÐL  Apply the chain until the results are no longer unique. Return the last
            unique result.
Dennis
fuente
Usar en lugar de también Fte haría admitir listas en tu lista.
Erik the Outgolfer
No, aquí se œ^basa en la promoción de entero a matriz. Dado que las matrices 1D no se promocionan a matrices 2D, no funcionará para nada excepto una matriz de números.
Dennis
Je ... Quiero decir, podrías haber usado ŒgWẎ$œ^/$€ẎµÐL... oh, espera, eso es demasiado ingenuo. : P
Erik the Outgolfer
4

retina ,17 15 bytes

+m`^(.+)¶\1$¶?

Pruébalo en línea!

¡Ahorré 2 bytes gracias a Neil y Martin!

Reemplaza cada par de números con nada. Este proceso se repite hasta que no se realizan cambios.

FryAmTheEggman
fuente
Se ideó una solución idéntica en Japt antes de detectar esto. Desafortunadamente, ambos fallamos en entradas como -89 89 -87 -88 -88, que salidas --87.
Shaggy
1
@ Shaggy Gracias, lo corregí agregando una verificación de límites y usando _para denotar negativos, como es común en algunos idiomas.
FryAmTheEggman
Desde entonces descubrí que esto también fallará _89 89 _87 _8 _88, produciendo _89 89 _87 8. Lo siento: \
Shaggy
@ Shaggy ¡No lo sientas! Gracias por encontrar el problema! Agregué otra verificación de límites para arreglar ese caso.
FryAmTheEggman
1
@FryAmTheEggman No estoy seguro de si eso es lo que Neil quiso decir, pero también podrías usarlo mpara convertir el \bs en ^y $.
Martin Ender
3

Mathematica 29 bytes

Esto elimina repetidamente pares de elementos adyacentes iguales, a_,a_hasta que no quede ninguno.

#//.{b___,a_,a_,c___}:>{b,c}&
DavidC
fuente
3

Python 2 , 57 bytes

r=[]
for x in input():r+=x,;r[-2:]*=r[-2:-1]!=[x]
print r

Pruébalo en línea!

Construye iterativamente la lista de salida agregando el siguiente elemento, luego cortando el final si el elemento anexado es igual al anterior. Verificar el penúltimo elemento r[-2:-1]!=[x]resulta incómodo porque es posible que la lista tenga una longitud de solo 1.

xnor
fuente
Impresionante respuesta, bien hecho :)
musicman523
2

Jalea , 15 bytes

Œr;ṪḂ$$€x/€FµÐL

Pruébalo en línea!

Explicación

Œr;ṪḂ$$€x/€FµÐL  Main Link
Œr               Run-length encode
  ;              Concatenate (?)
       €         For each element
   ṪḂ$$          Is the last element odd?
          €      For each element    // Non-breaking alternative
        x/       Reduce by repeating // for run-length decode
           F     Flatten
            µ    (New monadic link)
             ÐL  Repeat until results are no longer unique

-1 byte gracias a millas, y arreglado :)

Hiperneutrino
fuente
@FryAmTheEggman Fixed; ¡Gracias!
HyperNeutrino
No estoy seguro si arrojar un error y dejar la salida vacía cuenta como una solución correcta. Usted programa tiros ValueError: not enough values to unpack (expected 2, got 0)para el caso de prueba [1,2,2,1]. También tenga en cuenta que la salida vacía es diferente []y 2es diferente de [2].
13 bytes con Œr;ṪḂ$$€ŒṙµÐL. Para evitar el error, reemplace Œṙcon x/€Fya que la decodificación de longitud de ejecución arroja un error cuando se le da una lista vacía. Para ver la salida como una lista, la viñeta ŒṘlo mostrará.
millas
La representación de @ThePirateBay Jelly de una lista vacía es, vacía, de un elemento, solo ese elemento y de varios elementos, una lista entre corchetes y separados por comas. El envío es de un enlace (función) no un programa completo (al igual que una lambda estaría en Python), para ver un lugar de vista más "normal" ÇŒṘen el pie de página para llamar al último enlace ( Ç) e imprimir una representación de Python ( ŒṘ) . Sin embargo, el error podría no ser aceptable.
Jonathan Allan
@JonathanAllan. Ok, me di cuenta de que la representación en cadena de una lista de Jelly es aceptable. El punto principal de mi primer comentario es mencionar que el error se produce cuando la lista se vacía.
2

JavaScript (ES6), 54 53 bytes

Guardado 1 byte gracias a @ThePirateBay

f=a=>1/a.find(q=>q==a[++i],i=-2)?f(a,a.splice(i,2)):a

Solución recursiva ingenua, puede ser mejorable.

ETHproducciones
fuente
Puede verificar el elemento actual y el anterior en lugar del actual y el siguiente, por lo que puede reemplazar i=0con i=-2y i-1con el icual es -1 byte en total.
@ guest44851 Gracias, pero ... ¿eso no significaría que tendría que cambiarlo i+1? (Intenté esto antes con mover el ++también y no pude resolverlo, aunque solo tuve alrededor de un minuto para hacerlo)
ETHproductions
Puedes ver que funciona correctamente .
@ThePirateBay ¡Por Dios, tienes razón! ¿Pero cómo?
ETHproductions
2

Python 2 , 73 bytes

Como no tengo suficiente reputación para comentar: acabo de cambiar la respuesta de @officialaimm para usar r! = [] En lugar de len (r) para guardar un byte. ¡Una solución muy inteligente para ti, @officialaimm!

r=[]                            # create list that will hold final results. A new list is important because it needs to be removable.
for i in input():               
 if r!=[]and r[-1]==i:r.pop()   # Ensure that we have at least 1 char added to the list (r!=[])... or that the last character of our final result isn't the current character being scanned. If that is, well, remove it from the final list because we do not want it anymore
 else:r+=[i]                    # Shorthand for r.append(i). This adds i to the final result
print r

Pruébalo en línea!

Es, de nuevo, demasiado tarde ... ¿por qué aún estoy despierto?

Raphaël Côté
fuente
2

Python, 60 58 bytes

f=lambda a:a and(a[:1]+f(a[1:]))[2*(a[:1]==f(a[1:])[:1]):]

Pruébalo en línea!

Anders Kaseorg
fuente
[a[0]]esa[:1]
xnor
@xnor Así es. ¡Gracias!
Anders Kaseorg
2

MATL , 7 bytes

t"Y'oY"

Para algunos de los casos de prueba donde el resultado está vacío, el programa sale con un error, pero en cualquier caso produce la salida correcta (vacía).

Pruébalo en línea! O verifique los casos de prueba con salida no vacía .

Explicación

t     % Implicit input. Duplicate
"     % For each (i.e. do as many times as input size)
  Y'  %   Run-length encode. Gives array of values and array of run lengths
  o   %   Parity, element-wise. Reduces run-lengths to either 0 or 1
  Y"  %   Run-length decode. Gives array of values appearing 0 or 1 times;
      %   that is, removes pairs of consecutive values
      % Implicit end. Implicit display

Considerar entrada

0 0 0 1 2 4 4 2 1 1 0

Cada iteración elimina pares de pares consecutivos. La primera iteración reduce la matriz a

0 1 2 2 0

Los dos valores 2que ahora son adyacentes no eran adyacentes en la matriz inicial. Es por eso que se necesita una segunda iteración, que da:

0 1 0

Otras iteraciones dejarán esto sin cambios. El número de iteraciones requeridas está limitado por el tamaño de entrada.

Un resultado intermedio vacío hace que la función de decodificación de longitud de ejecución ( Y") falle en la versión actual del lenguaje; pero la salida está vacía según sea necesario.

Luis Mendo
fuente
¿Podría agregar una explicación? Me gustaría entender cómo me golpeaste tan profundamente. : P
Dennis
@Dennis ¡Seguro! Lo habia olvidado. Hecho :-)
Luis Mendo
1
Ah, RLE empuja dos matrices. Eso es útil
Dennis
2

Código de máquina x86 (modo protegido de 32 bits), 36 bytes

52
8B 12
8D 44 91 FC
8B F9
8D 71 04
3B F0
77 10
A7
75 F9
83 EF 04
4A
4A
A5
3B F8
75 FB
97
EB E7
58
89 10
C3

Los bytes anteriores del código de máquina definen una función que toma una matriz como entrada, contrae duplicados adyacentes en el lugar y regresa a la persona que llama sin devolver un resultado. Sigue la __fastcallconvención de llamada , pasando los dos parámetros en los registros ECXy EDX, respectivamente.

El primer parámetro ( ECX) es un puntero al primer elemento en la matriz de enteros de 32 bits (si la matriz está vacía, puede apuntar a cualquier parte de la memoria). El segundo parámetro ( EDX) es un puntero a un entero de 32 bits que contiene la longitud de la matriz.

La función modificará los elementos de la matriz en el lugar, si es necesario, y también actualizará la longitud para indicar la nueva longitud de la matriz contraída. Este es un método un poco inusual para tomar entradas y devolver salidas, pero realmente no tiene otra opción en lenguaje ensamblador. Como en C, las matrices se representan realmente en el lenguaje como un puntero al primer elemento y una longitud . Lo único un poco extraño aquí es tomar la longitud por referencia , pero si no lo hiciéramos, no habría forma de acortar la matriz. El código funcionaría bien, pero el resultado contendría basura, porque la persona que llama no sabría dónde detener la impresión de elementos desde la matriz contraída.

Mnemónicos de ensamblaje sin golf:

; void __fastcall CollapseAdjacentDuplicates(int * ptrArray, int * ptrLength);
; ECX = ptrArray              ; ECX = fixed ptr to first element
; EDX = ptrLength
   push  edx                  ; save pointer to the length
   mov   edx, [edx]           ; EDX = actual length of the array
   lea   eax, [ecx+edx*4-4]   ; EAX = fixed ptr to last element 

FindAdjacentPairs:
   mov   edi, ecx             ; EDI = ptr to element A
   lea   esi, [ecx+4]         ; ESI = ptr to element B
FindNext:
   cmp   esi, eax             ; is ptr to element B at end?
   ja    Finished             ; if we've reached the end, we're finished
   cmpsd                      ; compare DWORDs at ESI and EDI, set flags, and increment both by 4
   jne   FindNext             ; keep looping if this is not a pair

; Found an adjacent pair, so remove it from the array.
   sub   edi, 4               ; undo increment of EDI so it points at element A
   dec   edx                  ; decrease length of the array by 2
   dec   edx                  ;  (two 1-byte DECs are shorter than one 3-byte SUB)
RemoveAdjacentPair:
   movsd                      ; move DWORD at ESI to EDI, and increment both by 4
   cmp   edi, eax             ; have we reached the end?
   jne   RemoveAdjacentPair   ; keep going until we've reached the end
   xchg  eax, edi             ; set new end by updating fixed ptr to last element
   jmp   FindAdjacentPairs    ; restart search for adjacent pairs from beginning

Finished:
   pop   eax                  ; retrieve pointer to the length
   mov   [eax], edx           ; update length for caller
   ret

La implementación fue inspirada por mi respuesta de C ++ 11 , pero se reescribió meticulosamente en el ensamblaje, optimizando el tamaño. El ensamblaje es un lenguaje de golf mucho mejor. :-)

Nota: Debido a que este código utiliza las instrucciones de cadena, es no asumir que el indicador de dirección es clara ( DF== 0). Esta es una suposición razonable en la mayoría de los entornos operativos, ya que el ABI generalmente requiere que el DF sea claro. Si esto no se puede garantizar, entonces se debe insertar una CLDinstrucción de 1 byte ( 0xFC) en la parte superior del código.

También, como se señaló, asume el modo protegido de 32 bits, específicamente, un modelo de memoria "plano", donde el segmento adicional ( ES) es el mismo que el segmento de datos ( DS).

Cody Gray
fuente
1

Lote, 133 bytes

@set s=.
:l
@if "%1"=="%2" (shift/1)else set s=%s% %1
@shift/1
@if not "%1"=="" goto l
@if not "%s:~2%"=="%*" %0%s:~1%
@echo(%*

Configuré s .porque Batch se confunde si solo hay duplicados. También tengo que usar shift/1para %0%s:~1%poder configurar la lista de argumentos en la nueva matriz y bucle.

Neil
fuente
¿Tengo que preguntar por que? Buena respuesta ... pero ¿por qué?
Zacharý
@ Zacharý Porque está ahí.
Neil
1
@ Zacharý En parte, una buena razón para jugar al golf en otros idiomas es porque esto podría ser útil . Nadie va a disparar un intérprete de Jelly en la vida real para hacer esto, ¡pero es posible que tengan que hacerlo en un archivo por lotes!
Cody Gray
Oh. eso tiene sentido.
Zacharý
1

Jalea , 12 bytes

ŒgṁLḂ$$€ẎµÐL

Un enlace monádico que toma y devuelve listas de números.

Pruébalo en línea! o ver un conjunto de pruebas

¿Cómo?

ŒgṁLḂ$$€ẎµÐL - Link: list
         µÐL - perform the chain to the left until no changes occur:
Œg           -   group runs (yield a list of lists of non-zero-length equal runs)
      $€     -   last two links as a monad for €ach run:
     $       -     last two links as a monad:
   L         -       length (of the run)
    Ḃ        -       modulo 2 (1 if odd, 0 if even)
  ṁ          -     mould (the run) like (1 or 0) (yields a list of length 1 or 0 lists)
        Ẏ    -   tighten (make the list of lists into a single list)
Jonathan Allan
fuente
ṁLḂ$$€es equivalente a lo ḣLḂ$$€que es equivalente a ṫḊ¿€3$lo que puede reemplazar ṫḊ¿€3aquí para formar un par dyad / nilad.
Erik the Outgolfer
Eso no funciona con, por ejemplo, una entrada con una ejecución de longitud 4. ¿Cuál es la entrada a la cola en cada iteración del ciclo while?
Jonathan Allan
Se supone que te queda una lista con 0 o 1 elementos. Si len (x) == 1, entonces regresará []mientras que si len (x) == 0 regresará 0, ambos valores falsos. La entrada a es, por supuesto, el valor actual, y tendrá el valor actual como argumento izquierdo y 3como derecho. Si len (x) == 4, entonces sería lo mismo ṫ3ṫ3o ṫ5dejarlo con usted [].
Erik the Outgolfer
Puedo ver lo que se supone que debe hacer, pero ¿está xen su descripción realmente el valor actual? Prueba esto por tamaño.
Jonathan Allan
Para ser sincero, no sé si ese es el código o un error :)
Jonathan Allan
1

05AB1E , 15 bytes

[γʒgÉ}€нÐγ‚€gË#

Pruébalo en línea!

Explicación

[γʒgÉ}€нÐγ‚€gË#
[               # Start infinite loop
 γ              # Group Array into consecutive equal elements
  ʒgÉ}          # Keep the subarrays with an uneven amount of elements
      €н        # Keep only the first element of each subarray
        Ð       # Triplicate the result on the stack
         γ      # Group the top element into consecutive equal elements
          ‚     # Wrap the top two items of the stack in an array
           €g   # Get the length of each subarray
             Ë# # Break if they are equal
                # Implicit print          
Datboi
fuente
1

05AB1E , 13 bytes

[DγʒgÉ}€нDŠQ#

Pruébalo en línea!

Explicación:

[DγʒgÉ}€нDŠQ# Implicit input
[             Start infinite loop
 D            Duplicate
  γ           Split into chunks of equal elements
   ʒ  }       Filter by
    g           Length
     É          Odd? (0=falsy 1=truthy)
       €      Foreach command
        н     Head
         D    Duplicate
          Š   Push c, a, b
           Q  Equal? (0=falsy 1=truthy)
            # Break if true (i.e. equal to 1)
Erik el Outgolfer
fuente
1

Pitón 2 , 74 70 66 bytes

  • Gracias @SteamyRoot por 4 bytes: r lugar de len(r)es suficiente para verificar el vacío de la lista / pila.
  • Gracias @ovs por 4 bytes: mejor si la condición [i]==r[-1:]

Python 2 , 66 bytes

r=[]
for i in input():
 if[i]==r[-1:]:r.pop()
 else:r+=[i]
print r

Pruébalo en línea!

officialaimm
fuente
1
Si el propósito de len(r)es solo verificar si la lista está vacía o no, debería poder reemplazarla solo r, creo.
SteamyRoot
Oh si gracias.
officialaimm
1
66 bytes
ovs
@ovs Muchas gracias, ¡eso es increíble! (y)
officialaimm
1
Versión alternativa de 66 bytes de longitud , aunque solo requiere tres líneas.
Jonathan Frech
0

Clojure, 100 bytes

#(loop[i % j[]](if(= i j)i(recur(mapcat(fn[p](repeat(mod(count p)2)(last p)))(partition-by + i))i)))

No estoy seguro si esto es lo más corto posible.

NikoNyrh
fuente
0

Bash, 82 bytes

cat>b
while cat b>a
perl -pe 's/(\d+) \1( |$)//g' a>b
! diff a b>c
do :
done
cat a

Probablemente hay una salida de todos esos cats, pero no lo sé.

NighttimeDriver50000
fuente
0

Casco , 10 bytes

ωoṁS↑o%2Lg

Pruébalo en línea!

Explicación

ωoṁS↑o%2Lg
ω           Repeat until fixed point
 o          the following two functions:
         g   a) group adjacent elements
  ṁ          b) map over groups and concatenate:
        L     length of group
     o%2      mod 2
   S↑         take that many elements of group
Zgarb
fuente
0

PHP, 81 bytes

    function f(&$a){for($i=count($a);--$i;)$a[$i]-$a[$i-1]||array_splice($a,$i-1,2);}

función, llame por referencia o pruébelo en línea .

falla por entrada vacía; insertar $i&&o $a&&antes --$ide arreglar.

Tito
fuente
0

V , 10 bytes

òͨ.«©î±î*

Pruébalo en línea!

Regex comprimido: :%s/\(.\+\)\n\1\n*. La nueva línea opcional es para que también funcione al final del archivo. Si supongo que hay una nueva línea después del final, serían 8 bytes ... pero eso parece un tramo

nmjcman101
fuente
0

cc , 84 78 bytes

[L.ly1-dsy0<A]sA[LtLtS.ly1+sy]sP[dStrdStr!=Pz1<O]sO[0syzdsz1<Oly0<Azlz>M]dsMxf

Pruébalo en línea!

Desempacarlo un poco, fuera de orden en algún intento de claridad:

  • [0syzdsz1<Olydsx0<Alx1+lz>M]dsMxfLa macro principal Mrestablece el contador ya 0, recupera el número de elementos en la pila, almacena esto en el registro zy luego ejecuta la macro Osi hay al menos dos elementos en la pila. Una vez que Ofinaliza, carga el contador yy lo copia en el registro xantes de verificar para asegurarse de que yno sea cero (lo que significa que la pila .tiene datos). Si este es el caso, se ejecuta macro A. Finalmente, comprueba si el tamaño original de la pila es mayor que el tamaño actual de la pila y, de ser así, se vuelve a ejecutar. Una vez que ha terminado, imprime la pila con f.
  • [dStrdStr!=Pz1<O]sOMacro Oalmacena temporalmente los dos elementos superiores en la pila en la pila t. Luego compara los dos primeros elementos y ejecuta macro Psi no son iguales. Finalmente, verifica si hay al menos dos elementos en la pila y se ejecuta solo si es así.
  • [LtLtS.ly1+sy]sPMacro Ptoma los dos elementos de la pila t, empuja el superior hacia la pila principal y empuja el siguiente hacia la pila .. Luego incrementa el contador y.
  • [L.ly1-dsy0<A]sAMacro Atoma la pila .y la vuelve a convertir en la pila primaria. Lo hace, disminuyendo el contador yhasta que no quede nada más que empujar.

Editado para explicación y para jugar golf de 6 bytes ya que estaba almacenando innecesariamente el tamaño de la pila.

brhfl
fuente
0

C ++ 11, 161 bytes

#include<vector>
#include<algorithm>
using V=std::vector<int>;void f(V&v){V::iterator i;while((i=std::adjacent_find(v.begin(),v.end()))!=v.end())v.erase(i,i+2);}

El código anterior define una función, fque toma una std::vector<int>referencia, la modifica para colapsar los duplicados adyacentes de acuerdo con la especificación, y luego regresa.

Pruébalo en línea!

Antes de verificar el recuento de bytes, pensé que este era un código bastante esbelto. Sin embargo, ¡más de 150 bytes no es tan bueno! O no soy muy bueno jugando al golf, o C ++ no es un lenguaje de golf muy bueno ...

Sin golf:

#include <vector>
#include <algorithm>

using V = std::vector<int>;

void f(V& v)
{
   V::iterator i;

   // Use std::adjacent_find to search the entire vector for adjacent duplicate elements.
   // If an adjacent pair is found, this returns an iterator to the first element of the
   // pair so that we can erase it. Otherwise, it returns v.end(), and we stop.
   while ((i=std::adjacent_find(v.begin(), v.end())) != v.end())
   {
        v.erase(i, i+2);   // erase this adjacent pair
   }
}
Cody Gray
fuente
C ++ no es el mejor lenguaje de golf. Buen uso de std::adjacent_find! Me pregunto si ha implementado esta función manualmente si sería más corto, ya que se puede quitar #include <algorithm>, así
musicman523
@ musicman523 Mi primer intento lo implementé a mano, aunque utilicé un algoritmo un poco diferente. Estaba adaptando la implementación de std::uniquehacer lo que necesitaba. Pero se necesita mucho código para hacer toda la lógica, y cuando me encontré std::adjacent_find, era bastante obvio que ese era un ganador en términos de tamaño del código.
Cody Gray
0

PHP, 74 bytes

function c(&$a){foreach($a as$k=>$v)$a[$k+1]===$v&&array_splice($a,$k,2);}

La función c llama por referencia para reducir la matriz. Pruébalo en línea .

Curiosamente, esto funciona en Php5.6 pero no en 7.

Progrock
fuente
0

R , 57 54 bytes

l=rle(scan());while(any(x<-!l$l%%2))l=rle(l$v[!x]);l$v

Pruébalo en línea!

usa una codificación de longitud de ejecución para eliminar pares.

Giuseppe
fuente