Recolher duplicatas adjacentes


22

Desafio

Dada uma lista de números inteiros, retorne a lista desses números inteiros após remover repetidamente todos os pares de itens iguais adjacentes.

Observe que, se você tiver um número ímpar de números iguais, um deles permanecerá, não fazendo parte de um par.

Exemplo:

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

Primeiro, você deve remover 0, 0, 4, 4e 1, 1para obter:

[0, 1, 2, 2, 0]

Agora, você deve remover 2, 2:

[0, 1, 0]

E este é o resultado final.

Casos de teste

[] -> []
[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]

Pontuação

Isso é , então a resposta mais curta em cada idioma vence!


Sandbox para aqueles que podem ver as postagens excluídas
musicman523

Não importa, eles são todos iguais. O significado desta frase é que os [14, 14, 14]colapsos para[14]
musicman523

Leia mal o desafio, desculpe. Pensei que você tinha que remover todos os pares de números crescentes de 1 ( 1,2, 11,12, etc.)
Stephen

Podemos considerar a entrada como uma string delimitada?
Shaggy

2
Você poderia adicionar um caso de teste como -89,89,-87,-8,-88? Tanto minha solução Japt (não publicada) quanto a solução Retina de Fry falham por aí, produzindo --87,8.
Shaggy

Respostas:


5

Gelatina , 10 bytes

Œgœ^/€FµÐL

Experimente online!

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

Usar em vez de Ffaria com que você também suporte listas na sua lista.
Erik the Outgolfer

Não, œ^depende da promoção de número inteiro para matriz aqui. Como matrizes 1D não são promovidas para matrizes 2D, ele não funcionará para nada, exceto para uma matriz de números.
Dennis

Heh ... quero dizer, você poderia ter usado ŒgWẎ$œ^/$€ẎµÐL... oh, espere, isso é muito ingênuo. : P
Erik the Outgolfer

4

Retina ,17 15 bytes

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

Experimente online!

Economizou 2 bytes graças a Neil e Martin!

Substitui cada par de números por nada. Esse processo faz um loop até que nenhuma alteração seja feita.


Trabalhou uma solução idêntica em Japt antes de detectar isso. Infelizmente, nós dois falhamos em entradas como -89 89 -87 -88 -88, quais saídas --87.
Shaggy

1
@ Shaggy Obrigado, corrigi adicionando uma verificação de limite e usando _para denotar negativos, como é comum em alguns idiomas.
FryAmTheEggman

Desde então, descobri que isso também falhará na _89 89 _87 _8 _88saída _89 89 _87 8. Desculpe: \
Shaggy

@ Shaggy Não se desculpe! Obrigado por encontrar o problema! Eu adicionei outra verificação de limite para corrigir esse caso.
FryAmTheEggman

1
@FryAmTheEggman Não tenho certeza se é isso que Neil quis dizer, mas você também pode usar mpara transformar \bs em ^e $.
Martin Ender

3

Mathematica 29 bytes

Isso remove repetidamente pares de elementos adjacentes iguais, a_,a_até que não haja mais nenhum.

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

3

Python 2 , 57 bytes

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

Experimente online!

Constrói iterativamente a lista de saída anexando o próximo elemento e, em seguida, cortando o final se o elemento anexado for igual ao anterior. Verificar o penúltimo elemento r[-2:-1]!=[x]torna-se estranho, porque é possível que a lista tenha apenas um comprimento.


Impressionante resposta, bem feito :)
musicman523

2

Gelatina , 15 bytes

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

Experimente online!

Explicação

Œ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 graças a milhas e fixo :)


@FryAmTheEggman Fixed; obrigado!
21417 HyperNeutrino

Não tenho certeza se lançar um erro e deixar a saída vazia conta como uma solução correta. Você programa lança ValueError: not enough values to unpack (expected 2, got 0)para o caso de teste [1,2,2,1]. Observe também que a saída vazia é diferente []e 2é diferente de [2].

13 bytes com Œr;ṪḂ$$€ŒṙµÐL. Para evitar o erro, substitua Œṙpor, x/€Fpois a decodificação de comprimento de execução está lançando um erro ao receber uma lista vazia. Para ver o resultado como uma lista, o alinhamento ŒṘo mostrará.
miles

A representação de @ThePirateBay Jelly de uma lista vazia é - vazia, de um item - apenas esse item e de vários itens - uma lista entre colchetes e vírgula. O envio é de um link (função) e não de um programa completo (como um lambda seria no Python) - para ver um local de exibição mais "normal" ÇŒṘno rodapé para chamar o último link ( Ç) e imprimir uma representação do Python ( ŒṘ) . O erro pode não ser aceitável no entanto.
Jonathan Allan

@JonathanAllan. Ok, percebi que a representação de string de uma lista de Jelly é aceitável. O ponto principal do meu primeiro comentário é mencionar que o erro é gerado quando a lista fica vazia.

2

JavaScript (ES6), 54 53 bytes

Guardado 1 byte graças a @ThePirateBay

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

Solução recursiva ingênua, pode ser improvável.


Você pode verificar o elemento atual e o anterior em vez do atual e o próximo, para poder substituir i=0por i=-2e i-1com iqual é -1 byte no total.

@ guest44851 Obrigado, mas ... isso não significa que eu precisaria mudar para i+1? (Eu tentei isso antes com mover o ++bem e não conseguia entender, embora eu só tinha cerca de um minuto para fazê-lo)
ETHproductions

Você pode ver que ele funciona corretamente .

@ThePirateBay Por golly, você está certo! Mas como?
ETHproductions

2

Python 2 , 73 bytes

Como não tenho reputação suficiente para comentar: acabei de alterar a resposta de @officialaimm para usar r! = [] Em vez de len (r) para salvar um byte. Solução muito inteligente para você, @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

Experimente online!

É, de novo, tarde demais ... por que ainda estou acordado?



2

MATL , 7 bytes

t"Y'oY"

Em alguns casos de teste em que o resultado está vazio, o programa sai com um erro, mas, em qualquer caso, produz a saída correta (vazia).

Experimente online! Ou verifique os casos de teste com saída não vazia .

Explicação

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

Considere entrada

0 0 0 1 2 4 4 2 1 1 0

Cada iteração remove pares de pares consecutivos. A primeira iteração reduz a matriz para

0 1 2 2 0

Os dois valores 2que agora são adjacentes não eram adjacentes na matriz inicial. É por isso que é necessária uma segunda iteração, que fornece:

0 1 0

Outras iterações deixarão isso inalterado. O número de iterações necessárias é limitado pelo tamanho da entrada.

Um resultado intermediário vazio causa um Y"erro na função de decodificação de duração da execução ( ) na versão atual do idioma; mas a saída está vazia conforme necessário.


Você poderia adicionar uma explicação? Eu gostaria de entender como você me vence tão profundamente. : P
Dennis

@Dennis Sure! Eu esqueci. Feito :-)
Luis Mendo

1
Ah, o RLE empurra duas matrizes. Isso é útil.
Dennis

2

Código da 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

Os bytes acima do código de máquina definem uma função que recebe uma matriz como entrada, recolhe duplicatas adjacentes no local e retorna ao chamador sem retornar um resultado. Segue a __fastcallconvenção de chamada , passando os dois parâmetros nos registradores ECXe EDX, respectivamente.

O primeiro parâmetro ( ECX) é um ponteiro para o primeiro elemento na matriz de números inteiros de 32 bits (se a matriz estiver vazia, pode apontar para qualquer lugar na memória). O segundo parâmetro ( EDX) é um ponteiro para um número inteiro de 32 bits que contém o comprimento da matriz.

A função modificará os elementos da matriz no local, se necessário, e também atualizará o comprimento para indicar o novo comprimento da matriz recolhida. Esse é um método pouco usual para receber e retornar resultados, mas você realmente não tem outra opção na linguagem assembly. Como em C, matrizes são realmente representadas na linguagem como um ponteiro para o primeiro elemento e um comprimento . A única coisa um pouco estranha aqui é tomar o comprimento por referência , mas se não fizéssemos isso, não haveria maneira de reduzir a matriz. O código funcionaria bem, mas a saída conteria lixo, porque o chamador não saberia onde parar de imprimir elementos da matriz recolhida.

Mnemônicos de montagem não destruídos:

; 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

A implementação foi inspirada na minha resposta C ++ 11 , mas meticulosamente reescrita na montagem, otimizando o tamanho. Assembly é uma linguagem de golfe muito melhor. :-)

Nota: Como esse código usa as instruções de cadeia, é não assumir que a bandeira direção é clara ( DF== 0). Essa é uma suposição razoável na maioria dos ambientes operacionais, pois a ABI geralmente exige que o DF seja claro. Se isso não puder ser garantido, uma CLDinstrução de 1 byte ( 0xFC) precisará ser inserida na parte superior do código.

Também, como observado, assume o modo protegido de 32 bits - especificamente, um modelo de memória "simples", em que o segmento extra ( ES) é o mesmo que o segmento de dados ( DS).


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(%*

Defino s como .porque Lote fica confuso se houver apenas duplicatas. Eu também tenho que usar shift/1para que eu possa usar %0%s:~1%para definir a lista de argumentos para a nova matriz e loop.


Eu tenho que perguntar ... por quê? Boa resposta ... mas por quê?
Zacharý

@ Zacharý Porque está lá.
Neil

1
@ Zacharý Em parte, uma boa razão para jogar golfe em idiomas que não são de golfe é porque isso pode realmente ser útil . Ninguém vai acionar um intérprete Jelly na vida real para fazer isso, mas pode ser necessário fazer isso em um arquivo em lotes!
Cody Grey

Oh. isso faz sentido.
Zacharý

1

Gelatina , 12 bytes

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

Um link monádico que recebe e retorna listas de números.

Experimente online! ou veja uma suíte de testes

Quão?

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

ṁLḂ$$€é equivalente ao ḣLḂ$$€qual ṫḊ¿€3$você pode substituir ṫḊ¿€3aqui para formar um par díade / nilad.
Erik the Outgolfer

Isso não funciona com, por exemplo, uma entrada com uma extensão de comprimento 4. Qual é a entrada da desenfileiramento a cada iteração do loop while?
Jonathan Allan

Você deve ficar com uma lista com 0 ou 1 elementos. Se len (x) == 1, retornará []enquanto len (x) == 0 retornará 0, sendo ambos valores falsos. A entrada para é, obviamente, o valor atual e terá o valor atual como argumento à esquerda e 3à direita. Se len (x) == 4, seria o mesmo que ṫ3ṫ3ou ṫ5com você [].
Erik the Outgolfer

Eu posso ver o que é suposto fazer, mas xna sua descrição há realmente o valor atual? Experimente isso para ver o tamanho.
Jonathan Allan

Para ser honesto eu não sei se isso é o código ou um bug :)
Jonathan Allan


1

05AB1E , 15 bytes

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

Experimente online!

Explicação

[γʒ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          

1

05AB1E , 13 bytes

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

Experimente online!

Explicação:

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


1

Python 2 , 74 70 66 bytes

  • Obrigado @SteamyRoot por 4 bytes: em rvez de len(r)é suficiente para verificar o vazio da lista / pilha.
  • Obrigado @ovs por 4 bytes: melhor se condição [i]==r[-1:]

Python 2 , 66 bytes

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

Experimente online!


1
Se o objetivo de len(r)é apenas verificar se a lista está vazia ou não, você deve substituí-la por apenas r, eu acho?
22817 SteamyRoot

Ah sim, obrigado.
officialaimm


@ovs Muito obrigado, isso é incrível! y)
officialaimm

1
Versão alternativa de 66 bytes , apesar de exigir apenas três linhas.
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)))

Não tenho certeza se este é o mais curto possível.


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

Provavelmente existe uma saída para todos esses cats, mas eu não sei.


0

Casca , 10 bytes

ωoṁS↑o%2Lg

Experimente online!

Explicação

ω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

0

PHP, 81 bytes

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

função, chame por referência ou experimente online .

falha na entrada vazia; inserir $i&&ou $a&&antes --$ide corrigir.


0

V , 10 bytes

òͨ.«©î±î*

Experimente online!

Comprimido Regex: :%s/\(.\+\)\n\1\n*. A nova linha opcional é para que também funcione no final do arquivo. Se eu assumir que existe uma nova linha após o final, seria 8 bytes ... mas isso parece um trecho


0

dc , 84 78 bytes

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

Experimente online!

Descompactar um pouco, fora de ordem, em alguma tentativa de clareza:

  • [0syzdsz1<Olydsx0<Alx1+lz>M]dsMxfA macro principal Mredefine o contador ypara 0, recupera o número de itens na pilha, armazena isso no registro ze executa a macro Ose houver pelo menos dois itens na pilha. Quando Otermina, ele carrega o contador ye o copia no registro xantes de verificar para garantir que ynão seja zero (ou seja, a pilha .possui dados). Se for esse o caso, ele executa macro A. Por fim, verifica se o tamanho da pilha original é maior que o tamanho da pilha atual e, em caso afirmativo, é executado novamente. Depois de terminar, imprime a pilha comf .
  • [dStrdStr!=Pz1<O]sOA macro Oarmazena temporariamente os dois principais itens da pilha na pilha t. Em seguida, ele compara os dois itens principais e executa a macro Pse eles não forem iguais. Por fim, verifica se há ou não pelo menos dois itens na pilha e, se for o caso, executa-se.
  • [LtLtS.ly1+sy]sPMacro Ppega os dois itens da pilha t, empurra o de volta para a pilha principal e empurra o seguinte para a pilha .. Em seguida, incrementa o contador y.
  • [L.ly1-dsy0<A]sAA macro Apega a pilha .e a transforma novamente na pilha principal. Faz isso, diminuindo o contador yaté que não haja mais nada para empurrar.

Editado para explicação e para tirar 6 bytes de golfe, pois eu desnecessariamente armazenava o tamanho da pilha.


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

O código acima define uma função, fque usa uma std::vector<int>por referência, modifica-a no local para recolher duplicatas adjacentes de acordo com a especificação e, em seguida, retorna.

Experimente online!

Antes de verificar a contagem de bytes, achei que era um código bastante esbelto. Mais de 150 bytes, no entanto, não é tão bom! Ou eu não sou muito bom em golfe, ou C ++ não é uma linguagem muito boa de golfe…

Ungolfed:

#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
   }
}

C ++ não é a melhor linguagem de golfe. Bom uso de std::adjacent_find! Eu me pergunto se você implementou esta função se se seria mais curto, desde que você pode remover #include <algorithm>bem
musicman523

@ musicman523 Minha primeira tentativa foi implementada manualmente, embora eu tenha usado um algoritmo um pouco diferente. Eu estava adaptando a implementação std::uniquepara fazer o que eu precisava. Mas é preciso muito código para fazer toda a lógica e, quando eu me deparei std::adjacent_find, era bastante óbvio que esse era um vencedor em termos de tamanho do código.
Cody Grey

0

PHP, 74 bytes

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

A função c chama por referência para reduzir a matriz. Experimente online .

Curiosamente, isso funciona no Php5.6, mas não no 7.


0

R , 57 54 bytes

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

Experimente online!

usa uma codificação de comprimento de execução para remover pares.




Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.